27

私は最近右辺値参照を研究しており、オブジェクトの完全なコピーが作成されるあらゆる場所で値渡しを使用することは非常に有利であるという結論に達しました (完全な正当化については、右辺値参照演算子を追加するときに冗長コードを削減する方法などを参照してください)。オーバーロード?Want speed? Pass by value! ) のような場合、コンパイラはコピーを自動的に最適化して削除できるため、f(std::move(a));fとして定義されvoid f(A a);ます。

std::moveどこでも値渡しのマイナスの結果の 1 つは、次のような単純なケースであっても、すべてのコードが散らかってしまうことです。

void Object::value(A a) 
{
    value_ = std::move(a);
}

明らかに、私が次のことだけを書いた場合:

void Object::value(A a) 
{
    value_ = a;
}

aヒントがなくても、コンパイラが寿命の終わりに近づいていることを認識し、追加のコピーで私にペナルティを科さないことは難しくありません。実際、複雑な関数であっても、コンパイラはこれを認識できるはずです。

質問:

  1. この最適化は C++0x 標準で許可されていますか?

  2. コンパイラはそれを採用していますか?複雑なケースでも、つまり、関数が複数の行で構成されていますか?

  3. この最適化の信頼性はどの程度ですか?つまり、コンパイラーが戻り値の最適化を適用すると予想するのと同じくらい、コンパイラーがそれを利用することを期待できますか?

4

1 に答える 1

20

この最適化は C++0x 標準で許可されていますか?

いいえ。

コンパイラはそれを採用していますか?複雑なケースでも、つまり、関数が複数の行で構成されていますか?

いいえ。

この最適化の信頼性はどの程度ですか?つまり、コンパイラが戻り値の最適化を適用すると予想するのと同じくらい、コンパイラがそれを利用することを期待できますか?

A(const A&)andA(A&&)を print ステートメントで装飾し、関心のあるテスト ケースを実行する必要があります。これらのユースケースが設計の一部である場合は、左辺値引数をテストすることを忘れないでください。

正しい答えは、のコピーと移動にかかるコスト、実際Aの引数の数、Object::value許容できるコードの繰り返しの量によって異なります。

最後に、 「常に」や「どこでも」などの言葉を含むガイドラインには十分に注意してください。たとえば、私は時々使用gotoします。しかし、他のプログラマーは、「決して」などの言葉をgoto. gotoしかし、時折、スピードと明快さの両方で a に勝るものはありません。

foo(const A&) foo(A&&)オーバーのペアを好む時がありますfoo(A)。そして、そうしない時もあります。装飾された copy および move メンバーを使用した実験がガイドになります。

于 2011-05-22T17:31:27.873 に答える