4

C++0xの「12.8クラスオブジェクトのコピーと移動[class.copy]段落31」コピーの省略が発生した場合、正確には次のようになります。

特定の基準が満たされると、実装はクラス オブジェクトのコピー/移動の構築を省略できます [...]。コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます [...]:

  • クラスの戻り値の型を持つ関数の return ステートメントで、式が関数の戻り値の型と同じ cv-unqualified 型を持つ不揮発性の自動オブジェクト [...] の名前である場合、コピー/移動操作は可能です。自動オブジェクトを関数の戻り値に直接構築することで省略可能
  • [...]

そして今、これにより次のコードでコピーを回避できるかどうか疑問に思います

vector<string> gen(const char *fn) {
    if(fn == nullptr)  // this should prevent RVO
        return {"House", "Horse", "Hen"};
    vector<string> res;
    fillFromFile(res, fn);
    return res;  // copy elision possible?
}
int main() {
    vector<string> data = gen("users.dat");
}

それとも、そのルールは例に当てはまらないので、明示的に行う必要がありますか?

    return move(res);  // explicitly prevent copy

私の意図は、明らかなReturn Value Optimization (RVO)ifを排除することであったことに注意してください。

それとも、ここで完全に間違った方向に進んでいますか? 右辺値参照を使用できるreturnmoveに関連する変更がありましたよね?

4

2 に答える 2

3

はい、どちらの場合もコピー省略が可能/許可されています。

ただし、コンパイラの用語では、2 つのケースは少し異なります。return {"House", "Horse", "Hen"};名前のないオブジェクトを構築するため、通常の RVO が作動します。

return res;以前に構築された名前付きオブジェクトを返すため、少し複雑です。この最適化は通常、NRVO (名前付き戻り値の最適化) と呼ばれ、コンパイラがそれを実装することはあまり一般的ではありません。

MSVC は常に RVO を実装し、リリース ビルドで NRVO を実行します。

最近のバージョンの GCC は常に RVO と NRVO の両方を実行すると思います。

ところで、あなたの「if」がなぜ RVO に違いをもたらすのか、私にはよくわかりません。

于 2011-04-24T13:29:51.780 に答える
0

はい、コンパイラにはres、このコンテキストで右辺値のように扱うための特定の命令があり、resに移動されdataます。もちろん、コンパイラはここで RVO/NRVO を簡単に適用できます。これは、 で関数を呼び出さないことを静的に判断できるためですnullptr。最終的に、結果はまだ構築できるため、RVO/NRVO を妨げることさえありません。

于 2011-04-24T13:30:43.120 に答える