このコードがある場合:
class A { ... };
class B { ... };
void dummy()
{
A a(...);
B b(...);
...
}
a
変数とb
が逆の割り当て順序で破棄されることを知っています(b
最初に破棄され、次にa
); a
しかし、オプティマイザがandの割り当てと構築を決して交換しないと確信できb
ますか? またはvolatile
、それを強制するために使用する必要がありますか?
このコードがある場合:
class A { ... };
class B { ... };
void dummy()
{
A a(...);
B b(...);
...
}
a
変数とb
が逆の割り当て順序で破棄されることを知っています(b
最初に破棄され、次にa
); a
しかし、オプティマイザがandの割り当てと構築を決して交換しないと確信できb
ますか? またはvolatile
、それを強制するために使用する必要がありますか?
唯一の保証は、 の構築の観察可能な副作用 (つまり、volatile
オブジェクトへの読み取りと書き込み、および I/O 関数の呼び出し) が、 の構築のa
観察可能な副作用の前に発生することb
、およびa
required by b
willの副作用が発生することです。必要になる前に発生します。
それよりも厳密な順序付けが必要な理由を想像するのは困難ですが、オブジェクトを作成すると、の一部を初期化する前に が完全に初期化volatile
されることが保証されますが、コンストラクターからの一部のコードは、完成する前に発生する可能性があります。a
b
a
あなたが確信できる唯一のことは、 の構築と割り当てが のa
前になるということb
です。ステートメントを で区切る限り;
、最適化に関係なく、順番に実行されます。
volatile
それを変更することはありません。コンパイラがアクセス間で値をキャッシュするのを防ぎます。
わかりました、私はそのようなステートメントを標準で見つけますが、私は他の人の答えに少し混乱しています。
呼び出された関数の本体の実行の前後に特に順序付けられていない呼び出し元の関数(他の関数呼び出しを含む)のすべての評価は、呼び出された関数の実行に関して不確定に順序付けられます。(つまり、関数の実行は相互にインターリーブしません。)
これは、関数呼び出しが相互にインターリーブしないことを保証するだけですが、関数は不確定に順序付けられます。つまり、
評価AとBは、AがBの前にシーケンスされるか、BがAの前にシーケンスされる場合、不確定にシーケンスされますが、どちらがシーケンスされるかは指定されていません。