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


9

DOES C ++は、順序指定SPEC operator newとのコンストラクタAでをnew C(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());
}

3
C ++ 17、C ++ 14以前としてビルドしていますか?
StoryTeller-Unslander Monica

4
2つのメモ:これに「C」のタグを付けました。これは、そのタグの説明を読んでいないことを明確に示しています。しないでください。次に、「未定義の動作」(UB)について質問します。これは、C ++標準で使用される用語であり、何かが発生する可能性があること、および回避すべきことを示します。「不特定の動作」もあり、コードは技術的に問題がなく、UBを引き起こさないため、おそらくあなたが求めているものに近いでしょう。
Ulrich Eckhardt

1
@Ulrich Eckhardtご提案ありがとうございます。2つを混ぜました。
eddie kuo

回答:


11

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モードgcc10を使用してコンパイルしても同じ結果になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.