web-dev-qa-db-ja.com

演算子newとコンストラクターの引数の実行順序

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());
}
9
eddie kuo

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 でコンパイルしても同じ結果になります。

11
songyuanyao