問題タブ [rvo]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 戻り値の最適化に関する問題
私は C++ で RVO について少し読んでいて、奇妙な観察結果を見つけました。以下のコードを実行しました..
私はo / pを取得しました
testFunc への呼び出しの一時的なコピー変数は、実際にはいくつかの問題を引き起こします。var1 の ptr メンバーを削除します。これは、ポインタ 0xbfe3e918 のデストラクタへの呼び出しで確認できます。valgring の下では、このコードはメモリ リークを示しませんが、delete[] は無効です。
余分なデストラクタがどのように呼び出されているのか、対応するコンストラクタが同じものを呼び出さないのはなぜなのか、少し混乱しました??
c++ - この場合、Visual Studio が戻り値の最適化 (RVO) を実行しないのはなぜですか?
私は質問に答えて、コンパイラが戻り値の最適化 (RVO)を実行すると確信していたので、大きな型に対して値渡しを推奨していました。しかしその後、Visual Studio 2013 が私のコードで RVO を実行していないことが指摘されました。
ここで、Visual Studio が RVO を実行できないという質問を見つけましたが、その場合、結論は、本当に重要な場合は Visual Studio が RVO を実行するということのようです。私の場合、それは重要です。プロファイリング結果で確認したパフォーマンスに大きな影響を与えます。簡略化されたコードは次のとおりです。
コンパイラが からの戻り値の型で RVO を実行することを期待していgetBigFoo()
ます。Foo
しかし、代わりにコピーしているようです。
コンパイラが のコピー コンストラクタを作成することは承知していFoo
ます。また、準拠している C++11 コンパイラとは異なり、Visual StudioはFoo
. RVO は C++98 の概念であり、移動セマンティクスなしで動作します。
問題は、この場合に Visual Studio 2013 が戻り値の最適化を実行しない正当な理由があるかということです。
私はいくつかの回避策を知っています。の移動コンストラクターを定義できますFoo
。
これは問題ありませんが、move-constructors を持たないレガシー型がたくさんあります。これらの型で RVO に依存できることを知っておくとよいでしょう。また、一部の型は本質的にコピー可能ですが、移動はできません。
RVO から NVRO (戻り値の最適化という名前) に変更すると、Visual Studioは最適化を実行するように見えます。
NVRO は RVO よりも信頼性が低いと思っていたので、これは興味深いことです。
さらに興味深いのは、のコンストラクターを変更して、以下Foo
を作成して埋める場合vector
です。
それを移動する代わりに、RVOを実行しようとすると動作します:
これらの回避策のいずれかを使用して喜んでいますが、RVO が将来このように失敗する時期を予測できるようにしたいと考えています。
編集: @dyp からのより簡潔なライブ デモ
Edit2:なぜ私はちょうど書かないのreturn v;
ですか?
まず、それは役に立ちません。プロファイラーの結果は、Visual Studio 2013 は、私が書いただけでもベクターをコピーすることを示してreturn v;
います。この特定のコードを実際に修正しようとしているわけではありません。RVO が失敗する理由を理解しようとしているので、将来いつ失敗するかを予測できます。この特定の例を記述するより簡潔な方法であることは事実ですが、追加のコンストラクターパラメーターがあるreturn v;
場合など、単に記述できない場合がたくさんあります。Foo
c++ - ロックを返すときの C++11 の移動
本「C++ Concurrency in Action」で、次の方法を読んでいます
返されたときに head_lock が std::move-ed である理由がわかりません。移動の使用法と RVO に関する私の考えと直感は、C++11 の右辺値と移動のセマンティクスの混乱で共有されている意見と一致します (return ステートメント)
しかし、私は作者がよく知っていると信頼する傾向があります。std::move 戻り値が優れている場合、誰かが明確にすることができますか? ロックについて具体的に何かがありますか? ありがとう。
c++ - 複数のリターンを持つ RVO 演算子
クラスで RVO と連携して、作成される一時ファイルの数を減らす方法を示しています。
基本はわかりましたが、複数の値を組み合わせて 1 行に戻す方法を理解するのに苦労しています。
単一の一時的な最適化については、かなり簡単に理解できました
次のように削減できます。
ただし、複数の値を返す関数にこれを適用する方法がわかりません。例えば:
その背後にある私のプロセスは次のようになります。
" " というエラーが表示されますno argument takes the value (float, float)
。
初期を再編成する必要がありますか
Vect2D 演算子 - ( const Vect2D &tmp ) const;
内部で 2 つの float 引数を取るには? それとも私はこれについて間違った方法で考えていますか?
ありがとうございました、
E: ダブル フロート演算子を使用する必要があると私が考えていたことを確認してくれた Matt と Jerry に感謝します。
c++ - ベクトル参照を渡すと、そのデータの所有権が譲渡されますか?
ベクターとそのデータの所有権を渡したり譲渡したりする最良の方法は何ですか?
理想的な世界では、次のように機能します。
ローカル変数への参照を返しているため、これは機能しません。
このベクトル出力を使用boost::unique_ptr
または処理することは可能ですか? boost::shared_ptr
(C++11 の unique_ptr は使えません!)
c++ - C++11 高価な右辺値一時
押して操作する軽いオブジェクトがいくつかあるので、それらをより複雑なものに含めたいと思います。変更しないままにしておくべきルックアップ テーブルがあります。アイデアは単純に見えますが、これを行う 1 行で --b += c(a);
高価な一時ファイルが作成されます。
私は RVO と C++11 の右辺値について調べてきましたが、導入された中間体を完全に排除するのに十分なほど頭を包むことはできません。上記では、rhs のコンストラクターが使用可能であるため、1 つしか作成しません。最初はこれを持っていました。
しかし、私の直感に反して、結果はcount
2 でさえありました。コンパイラが私の意図を理解していないのはなぜですか?
c++ - 戻り値が NRVO の最初に宣言されたローカルである必要があるのはなぜですか?
コンパイラが名前付き戻り値の最適化 (NRVO) を実行できるようにするには、戻り値を関数本体の他の値より前に宣言する必要があることを理解しています。これは、例外が発生した場合のスタックの巻き戻しの順序が原因であると思われますが、よくわかりません。名前付きの戻り値が関数本体で最初に宣言されなければならない理由は何ですか?
使用事例:
編集: これを理解するのを手伝ってくれてありがとう、すべての回答者に感謝します。チャンドラー・カルースの声明がここにあると疑い始めています。それを誤解します。戻り変数を最初に宣言することは重要ではないようです。