C++仕様では、new C(A())
にoperator new
の順序とA
のコンストラクターを指定していますか。
g ++はA()
-> new
-> C()
の順序にしますが、clang ++はnew
-> A()
-> C()
。
不特定の動作が原因の違いですか?
g ++:7.4.0 clang ++:10.0.0
#include <iostream>
#include <cstdlib>
struct A {
A() {
std::cout << "call A()\n";
}
};
struct C {
C(A) {
std::cout << "call S()\n";
}
void *operator new(size_t s) {
std::cout << "call new()\n";
return malloc(s);
}
};
int main() {
void *p = new C(A());
}
Clangは正しいです。 C++ 17以降、実行順序は保証されています。 [expr.new]/19
割り当て関数の呼び出しは、 new-initializer 内の式の評価の前にシーケンスされます。
_operator new
_(割り当て関数)が最初に呼び出され、次に新しい初期化子(つまり、A()
)での式の評価が呼び出されることになっています。
C++ 17以前では、順序は保証されていません。 [[expr.new]/18 (C++ 14)
割り当て関数の呼び出しは、 new-initializer 内の式の評価に関して不確定に順序付けられます。
GccはC++ 17(およびそれ以降)に準拠していないようです。 C++ 2aモードのgcc1 でコンパイルしても同じ結果になります。