問題タブ [copy-elision]
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++ - Visual C++ 2010 Beta 2 でのコピー省略
私はWant Speedを読んでいましたか?C++ Next ブログのPass by Valueでは、C++0x でのコピー省略と移動セマンティクスの感触をつかむために次のプログラムを作成しました。
Visual C++ 10.0 (ベータ 2) でリリース モードでコンパイルしたときに得られる出力は次のとおりです。
インスタンス 1 を構築する (データなし)
インスタンス 2 を構築する (データあり)
2 の移動からインスタンス 3 を構築する インスタンス
2を破棄する3 から
インスタンス 1 に割り当てるインスタンス
3を破棄する インスタンス
1を破棄する
省略された移動: いいえMove assign from RVO simple:
インスタンス 1 の構築 (データなし)
インスタンス 2 の構築 (単純なデータあり)
インスタンス 1 から 2 への割り当て
インスタンス 2の
破棄 インスタンス 1の破棄
省略された移動: はいNRVO からの割り当ての移動:
インスタンス 1 の構築 (データなし)
インスタンス 2 の構築 (データあり) 2
からインスタンス 1 への割り当て
インスタンス 2の
破棄 インスタンス 1の破棄
省略された移動: はいNRVO シンプルからの割り当ての移動:
インスタンス 1 の構築 (データなし)
インスタンス 2 の構築 (単純なデータあり)
インスタンス 1 から 2 への割り当て
インスタンス 2の
破壊 インスタンス 1の破壊
省略された移動: はい
しかし、私は一つのことに困惑しています。ご覧のとおり、最初の動きを除いてすべての動きが省略されています。コンパイラが 86 行目の MoveableClass(std::vector) では RVO を実行できないのに、97 行目の MoveableClass(int) では実行できるのはなぜですか? これは単なる MSVC のバグですか、それとも正当な理由がありますか? 正当な理由がある場合、91 行目で MoveableClass(std::vector) に対して NRVO を実行できるのはなぜですか?
幸せな気持ちで眠れるように理解したいです。:)
c++ - コピー省略とは何ですか? また、コピー アンド スワップ イディオムをどのように最適化しますか?
Copy and Swapを読んでいました。
Copy Elision のいくつかのリンクを読んでみましたが、それが何を意味するのかを正しく理解できませんでした。誰かがこの最適化とは何か、特に次のテキストの意味を説明してもらえますか
これは単なる利便性の問題ではなく、実際には最適化です。パラメーターが左辺値 (別の非 const オブジェクト) にバインドされている場合、パラメーターの作成中にオブジェクトのコピーが自動的に作成されます。ただし、s が右辺値 (一時オブジェクト、リテラル) にバインドされている場合、通常、コピーは省略され、コピー コンストラクターとデストラクターへの呼び出しが節約されます。パラメーターが const 参照として受け入れられる代入演算子の以前のバージョンでは、参照が右辺値にバインドされている場合、コピー省略は発生しません。これにより、追加のオブジェクトが作成および破棄されます。
c++ - 戻り値の自動変数のコピー省略
C++0xの「12.8クラスオブジェクトのコピーと移動[class.copy]段落31」でコピーの省略が発生した場合、正確には次のようになります。
特定の基準が満たされると、実装はクラス オブジェクトのコピー/移動の構築を省略できます [...]。コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます [...]:
- クラスの戻り値の型を持つ関数の return ステートメントで、式が関数の戻り値の型と同じ cv-unqualified 型を持つ不揮発性の自動オブジェクト [...] の名前である場合、コピー/移動操作は可能です。自動オブジェクトを関数の戻り値に直接構築することで省略可能
- [...]
そして今、これにより次のコードでコピーを回避できるかどうか疑問に思います
それとも、そのルールは例に当てはまらないので、明示的に行う必要がありますか?
私の意図は、明らかなReturn Value Optimization (RVO)if
を排除することであったことに注意してください。
それとも、ここで完全に間違った方向に進んでいますか? 右辺値参照を使用できるreturn
とmoveに関連する変更がありましたよね?
c++ - コンパイラは次のコピーを省略できますか?
私はまだ初心者のプログラマーです。時期尚早の最適化が悪いことは知っていますが、巨大なものをあちこちにコピーすることも悪いことだと知っています。
私はコピー省略について読みましたが、それは同義語ですが、たとえばウィキペディアの例では、コピー省略は、返されるオブジェクトが完全に構築されると同時に返された場合にのみ発生するように思えます。
ベクトルのようなオブジェクトは、通常、何かで満たされた場合にのみ意味を持ち、戻り値として使用されます。結局のところ、空のベクターは手動でインスタンス化できます。
では、このような場合でも機能しますか?
簡潔にするための悪いスタイル:
bar(vector & out, string text) を使用しても特に問題はありませんが、上記の方法は美的にも意図的にもはるかに見栄えがします。
c++ - コピーの省略を確実にすることは可能ですか?
コピーの省略は優れた最適化手法であり、場合によっては、コピーの省略に依存する方が、参照を「手動で」渡すよりも実際に高速になることがあります。
したがって、最大のパフォーマンスを得るために、コードパスに対してコンパイラによってコピーの省略が実行されるという事実に依存する重要なコードパスを特定したと仮定します。
しかし今、あなたはコンパイラの最適化に依存しています。
コピーの省略が実際に実行され、コピーの省略が実行できない場合にコンパイラ(または別のツール)に警告/エラーを生成させる(コンパイラ固有の、明らかに)方法はありますか?
__forceinline
(このようにマークされた関数がコンパイラーによってインライン化されていない場合に警告を生成するよりも、Visual C ++にリモートで類似したものを考えています。)
c++ - 重いオブジェクトを渡すC++0x
ある種の高価なオブジェクト(固定サイズではないベクトルとマップを含む)を生成する関数があるので、コピーc'torを呼び出さないようにします。
これまで、メソッドからstd :: shared_ptrを返し、それを使用しましたが、これは醜く、typedeffingを実際に使用できるようにする必要があると思います。
私は私を助けるかもしれない2つのことを知っています。最初にコピーの省略であり、2番目は移動セマンティクスです。
私の問題は、どちらも正しく使用する方法を知っていることです。私の調査によると、コピーの省略は完全にコンパイラーによって行われ、標準の一部ではありません。私は本当にこれだけに頼る必要はありません。
では、move assigmentが呼び出され、コンパイラーがコピーの省略を実行できないようにするために、それを適切に配置するにはどうすればよいですか。
この場合、これはこれをコーディングするための最も正しい方法ですか?そうでなければ、どうすればそれを改善できますか。C++0xのみの構成を使用できてうれしいです。
ところで:私のコンパイラはgcc4.6です
c++ - C++0x で移動/コピーを回避するより良い方法
この質問は、C++0x でラムダを渡すにはどうすればよいですか? の続きです。、しかしおそらくこれは質問をするためのより明確な方法です.
次のコードを検討してください。
次を出力します。
マクロ バージョンが何らかの形ですべての移動/コピー コンストラクター呼び出しを省略していることは明らかですが、関数バージョンはそうではありません。
C++0x では、多くのマクロを使用せずにすべての移動とコピーを削除する構文的に優れた方法があると思いますが、それを理解できません。
理由:
パラメータパックを構築するために、移動やコピーなしでそのようなコードを使用する予定です。
また、これらには、非パラメーター コードと比較して余分な移動/コピーがありません。
c++ - コピーの省略はcatchステートメントで発生する可能性がありますか?
副作用のあるコピーコンストラクターを持つ例外クラスについて考えてみます。
コンパイラはここでコピーコンストラクタの呼び出しをスキップできますか?
これはどうですか:
(はい、これはすべて非常に醜いことを知っています、これは別の質問に触発されました)
c++ - コンストラクターの省略をコピーしますか?
重複の可能性:
デストラクタが一度だけ呼び出されたのはなぜですか?
以下のコードを考えると、gccでの出力を理解できません。2つのオブジェクトが作成および破棄されることを期待していますが、代わりにコンストラクタとデストラクタへの呼び出しが1つだけ表示されます。ここで何が起こっているのですか?
g ++(4.4)でのこのコードの出力は次のとおりです。
gを入力する
コンストラクタ
gを終了します
メインを離れる前に
デストラクタ
c++ - 以下のコードで NRVO が g++ でキックする/しないのはなぜですか?
私は NRVO を調査しており、さまざまなコンパイラでサポートされていますが、奇妙な動作に遭遇しました。これはかなり混乱しています。
サンプルコード:
最適化レベル 2 (または 3) でコンパイルすると、出力は 2 つの異なるメモリ アドレスになります。ただし、私が理解している限り、関数コードは NRVO に対して有効です。
PS VS2010 でコンパイルされた同じコードと最適化レベル 2 は NRVO を使用します。
追加のコンストラクターを追加すると:
コンパイル後のアドレスは同じなので、NRVO が適用されていると思いますが、最適化レベルに関係なく発生します。
" X(const X& h) " は何らかの形で g++ に NRVO を使用することを暗示していますか? それともNRVOが全く適用されておらず何か違うのでしょうか?
前もって感謝します。
追加した。GCC バージョン:
$ g++ -v
Configured with: [....] -enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
gcc version 4.4.3
追加のテスト:X(const X& h)
コンストラクトと-fno-elide-constructors
g++ フラグを使用してコンパイルすると、「コピー」コンストラクターが呼び出され、予期される動作が行われます。それがなければ、NRVO は失敗します。異なるマシンでテスト: gcc 4.4.3 と gcc 4.3.* -> 同じ結果。
これまでのところ、__cxa_atexit (@yves の g++ のバージョンに存在) が何らかの形で異なる動作に影響を与えるかどうかはわかりません。(私が理解している限り、それとは関係ありませんが、それが呼び出し順序にもたらす変化を完全には理解していません)