a
静的ストレージ期間を持つグローバル オブジェクトであるため、メインの本体が実行される前に、事前に割り当てられたストレージで初期化されます。Test の呼び出しが静的オブジェクト構築の奇妙さの結果ではないと仮定すると、Test が呼び出されるまでa
に完全に構築されます。
a = new A;
A
この少し変わった代入は、オブジェクトや参照ではなく、へのポインターを代入しているため、標準のコピー代入操作 (のみ) にはなりません。それが実際にコンパイルされ、正確に何を呼び出すかA
は、 へのポインターを取る代入演算子があるかどうかA
、またはポインターから暗黙的に変換可能なものがあるA
かどうか、またはポインター(またはベースへのA
ポインター) を取る非明示的なコンストラクターがあるかどうかによって異なります。A
のクラスA
)。
編集後、コードはかなり異なることを行います!
概念的には、次のようなことを行います。
A *tmpa;
void *mem = ::operator new( sizeof(A) ); // ( or possibly A::operator new )
try
{
tmpa = new (mem) A; // placement new = default constructor call
}
catch (...)
{
::operator delete( mem );
throw;
}
a = tmpa; // pointer assignment won't throw.
このようなものを書き出すことの危険は、オリジナルには存在しない多くのシーケンス ポイントを暗黙のうちに追加することです。さらに、コンパイラは、動作する限り、このように見えないコードを生成することができます。実行中のプログラムが判断できる限り、これによって書かれたかのように。(現在の) 言語は他のスレッドとの相互作用について何も述べていないため、この「あたかも」ルールは実行中のスレッドにのみ適用されます。
このためには、実装によって提供される特定の動作保証 (存在する場合) を使用する必要があります。