問題タブ [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++ - パラメータを返すときにRVOが許可されないのはなぜですか?
[C ++ 11:12.8 / 31]に記載されています:
コピーの省略と呼ばれるこのコピー/移動操作の省略は許可されています[...]:
—クラスreturn型を持つ関数のreturnステートメントで、式が、関数return型と同じcv-unqualified型を持つ不揮発性自動オブジェクト(関数またはcatch-clauseパラメーター以外)の名前である場合、自動オブジェクトを関数の戻り値に直接構築することにより、コピー/移動操作を省略できます。
これは、
印刷します
2番目のコピーコンストラクタが必要なのはなぜですか?コンパイラは単にxの寿命を延ばすことはできませんか?
c++ - コピーの省略は異なる結果を引き起こします
私がこの架空の、奇妙で直感的でない状況にあるとしましょう
a
コピーの省略とは、デフォルトのコンストラクターだけで初期化され、bはコピーコンストラクターで初期化されることを意味します。また、(少なくともgccでは)コピーの省略を行わないようにコンパイラーに指示できることも知っています。
私の質問は、コンパイラがこのクラスのためだけにコピーの省略を使用しないようにする方法がありますか?
実際の状況での答えは、99.9%の確率で他の方法を見つけることであり、0.01%のケースはありません(これは実際の架空の質問であり、「架空の質問」ではありません)。
c++ - このコピーコンストラクターの省略ですか?
次のコードは、コピーコンストラクターを呼び出していません。
出力:
コピーコンストラクターのエリジオンですか?
c++ - ファクトリ関数からインプレースでコピー不可能なメンバー (または他のオブジェクト) を初期化する
この構文が正当であるためには、クラスに有効なコピーまたは移動コンストラクターが必要です。
C++03 では、コンパイラがコピー コンストラクターに触れるのを防ぐために、コピー省略に頼ることがかなり一般的でした。定義が存在するかどうかに関係なく、すべてのクラスには有効なコピー コンストラクターシグネチャがあります。
C++11 では、コピー不可能な型は を定義する必要C( C const & ) = delete;
があり、関数への参照は使用に関係なく無効になります (移動不可能な場合も同様)。(C++11 §8.4.3/2)。たとえば、GCC は、そのようなオブジェクトを値で返そうとすると文句を言います。コピーの省略は役に立ちません。
幸いなことに、抜け穴に頼るのではなく、意図を表現するための新しい構文もあります。このfactory
関数は波括弧初期化リストを返して、結果の一時的なインプレースを構築できます。
編集:疑問がある場合、このreturn
ステートメントは次のように解析されます。
- 6.6.3/2: 「ブレース初期化リストを含む return ステートメントは、指定された初期化子リストからのコピー リスト初期化 (8.5.4) によって、関数から返されるオブジェクトまたは参照を初期化します。」
- 8.5.4/1: 「コピー初期化コンテキストでのリスト初期化は、コピーリスト初期化と呼ばれます。」¶3: 「T がクラス型の場合、コンストラクターが考慮されます。適用可能なコンストラクターが列挙され、オーバーロードの解決を通じて最適なコンストラクターが選択されます (13.3、13.3.1.7)。」
copy-list-initializationという名前に惑わされないでください。8.5:
13: 初期化の形式 (かっこまたは を使用
=
) は一般に重要ではありませんが、初期化子または初期化されるエンティティがクラス型を持つ場合は問題になります。下記参照。初期化されるエンティティにクラス型がない場合、括弧で囲まれた初期化子の式リストは単一の式になります。14:
T x = a;
引数の受け渡し、関数の戻り、例外のスロー (15.1)、例外の処理 (15.3)、および集合メンバーの初期化 (8.5.1) と同様にフォームで発生する初期化は、コピー初期化と呼ばれます。
copy-initialization とその代替であるdirect-initializationの両方は、初期化子が波括弧初期化リストである場合、常に list-initialization に従います。を追加しても意味的な効果はありません=
。これが、リスト初期化が非公式に均一初期化と呼ばれる理由の 1 つです。
違いがあります。直接初期化は、コピー初期化とは異なり、明示的なコンストラクターを呼び出す場合があります。コピー初期化は、変換時に一時オブジェクトを初期化し、それをコピーしてオブジェクトを初期化します。
ステートメントのcopy-list-initializationのreturn { list }
指定は、まったく同等の構文を betemp T = { list };
に指定するだけです。ここで、=
copy-initialization を示します。コピー コンストラクターが呼び出されることをすぐに意味するわけではありません。
-- 編集を終了します。
次に、関数の結果を右辺値参照に受け取って、一時的なものをローカルにコピーしないようにすることができます。
問題は、コピー不可、移動不可の型を返すファクトリ関数から非静的メンバーを初期化する方法です。参照メンバーは一時の有効期間を延長しないため、参照のトリックは機能しません。
集約初期化は考慮していないことに注意してください。これは、コンストラクターの定義に関するものです。
c++ - 二項演算子 + オーバーロードの戻り値は const である必要があり、最適化を妨げる可能性がありますか?
サンプルコードを考えると:
operator+() が実際に const Integer を返すべきかどうか疑問に思い始めました。「Thinking in C++」の Bruce Eckel は、同様のケースの演算子のオーバーロードの例を提供しており、戻り値の型で const 修飾子を好むようです。それを使用する必要がありますか?その理由は?
一方、このクラスを使用してみましょう。
aとbの合計としてcを作成する場合、コンパイラはほとんどの場合コピー省略を実行し、Integer::operator+() はcが占める場所にその結果を直接作成します (「速度が必要ですか? 値で渡す」を参照してください)。しかし、Integer::operator+() の戻り値の型が const として宣言されている場合、ターゲットが非 const であるため、コンパイラは強制的にコピーを実行しませんか?
c++ - c ++ 11では、仮想関数は移動セマンティクスを使用して大きな値を効率的に返すことができますか?
通常、これは大きな値のコピーを伴わないように最適化されます(astd::vector
は移動セマンティクスが有効になっているため)。
関数が仮想メソッドの場合、これも同じ方法で最適化できますか?
つまり、実行時に呼び出された関数が選択されている場合でも、移動セマンティクスは機能しますか?
c++ - コピーの省略と戻り値の最適化とは何ですか?
コピーの省略とは何ですか?(名前付き)戻り値の最適化とは何ですか?それらは何を意味しますか?
どのような状況で発生する可能性がありますか?制限は何ですか?
- この質問を参照された場合は、おそらく紹介を探しています。
- 技術的な概要については、標準リファレンスを参照してください。
- ここで一般的なケースを参照してください。
c++ - コンストラクターの連鎖呼び出しでのコピー省略
コピーの省略のため、内部コピーが保持される限り、通常はオブジェクトを値で渡すことが推奨されます。次の状況はどうでしょうか。
連鎖コピーは引き続き省略されますか、つまり、1、3、および 5 が望ましいですか? それとも2、4、6?インライン化に依存しますか?
c++ - C++11 の右辺値、ムーブ セマンティクス、およびパフォーマンスの理解
次のコードを検討してください
この関数getName()
は一時オブジェクトを返します。C++03 では、string
gets のコピー コンストラクターが呼び出され、一時オブジェクトが破棄されることを理解しています。実際、コンパイラ (少なくとも GCC 4.7 では) は、オブジェクトを作成せずname
に一時オブジェクト自体に置き換え、一時オブジェクトを破棄しないことで、5 行目を最適化しているようです。MyVector
( std::stringではなく、クラスで試しました)
C++11 標準で定義されているように、
getName()
右辺値を返していますか?上記の 5 行目で、文字列のどのコンストラクターが呼び出されますか (移動またはコピー) ?
std::move()
移動コンストラクターが呼び出されるようにする 必要がありますか?移動セマンティクスでは、コンパイラが提供する「コピー省略」最適化よりも効率が悪いですか?