5

Intel コンパイラが std::array オブジェクトの戻り値の最適化を生成しないことを発見しました。私のプログラムの内側のループにたまたまある次のコードは、可能な限り最適化されていません。

std::array<double, 45> f(const std::array<double, 45>& y) {
    auto dy_dt = std::array<double, 45>( );
    ...

    return dy_dt;
}

この動作は、標準ライブラリの実装が std::array のコピー コンストラクターを明示的に定義していないという事実に起因することがわかりました。次のコードは、次のことを示しています。

class Test {
public:
    Test() = default;
    Test(const Test& x);
};

Test f() {
    auto x = Test( );

    return x;
}

でコンパイルすると

icpc -c -std=c++11 -qopt-report=2 test.cpp -o test.o

レポートファイルが表示されます

INLINE REPORT: (f(Test *)) [1] main.cpp(7,10)

これは、コンパイラが RVO を生成することを証明します (f の署名が変更され、新しく作成されたオブジェクトを呼び出し側のスタックに配置できるようになります)。ただし、 を宣言する行をコメント アウトするTest(const Test& x);と、レポート ファイルに次のように表示されます。

INLINE REPORT: (f()) [1] main.cpp(7,10)

これは、RVO が発生していないことを証明しています。

RVO を定義する C++11 標準の 12.8.31 では、彼らが提供する例にはコピー コンストラクターがあります。では、これは Intel コンパイラの「バグ」なのか、それとも標準に準拠した実装なのか?

4

1 に答える 1

1

このプログラムは、One Definition Rule の違反により、診断を必要としない未定義の動作を引き起こします。

copy-constructor は、値によって返されるときにODR 使用されます -コピーの省略が行われた場合でも

ODR で使用される非インライン関数は、関数の定義が 1 つだけプログラムに表示されなければならないことを意味します。ただし、何も指定していないため、コピーコンストラクターの宣言により、コンパイラーが生成した定義が抑制されます。

于 2015-03-04T13:31:36.277 に答える