問題タブ [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++ - コピー省略の目に見える副作用
次のコードを検討してください。
でコンパイルすると
g++ -std=c++11 -fno-elide-constructors test.cpp
出力は
ctor ctor コピー 0
inは暗黙的に から構築され、Foo b = 10
コピーはから構築されるため、これは私が期待するものです。さらに、私のコピー コンストラクターは何もしないので、メンバーは残ります(クラス内で初期化されるため)。10
int
b
Foo
_a
0
ただし、コピー省略を使用すると
g++ -std=c++11 test.cpp
出力は
ctor ctor 10
控えめに言っても驚くべきことです。ここでコピー コンストラクターが省略されていることは理解していますが、これはコード パスの残りの部分に影響を与えるため、重大な副作用 (メンバーが 0 に初期化され、10 に初期化されるという事実) です。
この動作は正常ですか?
c++ - 自動およびコピー省略
auto を使用して特定のタイプにコミットする場合のコピー省略のルールは正確には何ですか? (参照: GotW - ほとんど常に auto )。
私の理解では、move/copy コンストラクターは、一般的には使用されていませんが、アクセス可能である必要があります。しかし、以下の例のunique_ptrとfstreamの違いは何ですか? ( noexceptと何か関係がありますか?)
c++ - コピーエリシオンの誤解
でコンパイルした後
g++ Copy.cpp -std=c++11 -fno-elide-constructors
出力は次のとおりです。
定義構成
構成をコピー
構成をコピー
そして私の質問は: なぜ 2 Copy Constr なのですか? 必要なコピーは1つだけだと思いました。
func1() が一時オブジェクトをスローし、この一時オブジェクトを別のメモリ領域にコピーする必要があり、その領域から再び func2() パラメータのコピーを作成する必要があると推測するかもしれませんが、私にとってはあいまいです。
詳しく説明していただけますか?
c++ - コピー省略が制限されているのはなぜですか?
私が注目しているコピー省略の 2 つの形式は、非常に制限されています。これは、return ステートメント内で、変数を一時変数で初期化する場合にのみ許可されます。したがって、これらにはコピー省略は含まれません。
これの理由は何ですか?それは技術的な制限ですか..それとも..?
c++ - テンプレート クラスで呼び出されるデストラクタが多すぎる (N)RVO 最適化
独自のスマート ポインター (C++ 11) とスタックを作成しようとしていますが、次の例で説明できる 1 つの問題があります。
出力:
ご覧のとおり、ここには非常に多くのデストラクタがあります。私の考えでは、copy elision と template-constructor の間の相互作用に何らかの問題がありますが、そのようなバグの理由が何であるかはわかりません。copy-constructorを追加して問題を修正し、explicit
コンパイラに template-constructor を強制的に使用させようとしました。
次の出力を得ました:
ここではすべて問題ないように見えますが、クリーンなソリューションには見えません。より良い代替手段はありますか?
c++ - スタック割り当てオブジェクトへのポインタとムーブ構造
注:これは、私がしばらく前に投稿した質問の完全な言い回しです。重複している場合は、もう一方を閉じてください。
私の問題は非常に一般的ですが、具体的な簡単な例に基づいて、より簡単に説明できるようです。オフィスの電力消費量をシミュレートしたいとします。照明と暖房しかないと仮定しましょう。
重要な点は次のとおりです。
1.Time
データ メンバーに移動できない、Light
またはHeating
その変更がこれらのクラスのいずれにも由来しないため。
2.Time
にパラメーターとして明示的に渡す必要はありませんLight
。実際、Light
プログラムのどの部分にも、パラメーターとして提供したくない への参照が存在する可能性がTime
あります。
これで、Simulation
コピー/移動が構築されていない限り、完全に見つかります。そうである場合は、コピー/移動も構築され、デフォルトで、Time へのポインターはコピー/移動元の古いインスタンスをLight
指しているからです。ただし、実際には、return ステートメントとオブジェクト作成の間で copy/move が構築されます。Time
Simulation
Simulation
SimulationBuilder::build()
main()
現在、問題を解決する方法はいくつかあります。
1: コピー省略に依存します。この場合(そして私の実際のコードでは)、コピーの省略は標準で許可されているようです。しかし必須ではなく、実際のところ、clang -O3 によって省略されることはありません。より正確に言うと、clang はSimulation
コピーを省略しますが、move ctor for を呼び出しますLight
。また、実装依存の時間に依存することは堅牢ではないことに注意してください。
2: で move-ctor を定義しSimulation
ます。
これは機能しますが、ここでの大きな問題はカプセル化を弱めることです:移動中により多くの情報が必要でSimulation
あることを知る必要があります。Light
この単純化された例では、これはそれほど悪くはありませんが、timePtr
直接ではなくLight
、そのサブサブサブメンバーの 1 つにあると想像してください。それから私は書かなければならないでしょう
これは、カプセル化とデメテルの法則を完全に破ります。関数を委任するときでさえ、私はそれが恐ろしいと思います。
Time
3: によって監視されているある種のオブザーバー パターンを使用し、メッセージを受信するときにポインターを変更するLight
ように、コピー/移動が構築されているときにメッセージを送信します。Light
私はそれの完全な例を書くのが面倒だと告白しなければなりません。
4: で所有ポインタを使用しますSimulation
。
が移動Simulation
すると、Time
メモリは ではないため、 のポインタLight
は無効になりません。実際、これは他のほとんどすべてのオブジェクト指向言語が行うことです。すべてのオブジェクトはヒープ上に作成されるからです。今のところ、私はこの解決策を支持していますが、まだ完全ではないと考えています。B. Stroustrup が、必要のないときはポインタを使用すべきではなく、必要な場合は多かれ少なかれポリモーフィックであることを意味すると言っているのを聞いたことがあります。
5:Simulation
返されることなく、その場で構築しSimulationBuilder
ます (その後、コピー/移動 ctor/代入をSimulation
すべて削除できます)。例えば
今、私の質問は次のとおりです。
1: どのようなソリューションを使用しますか? もう一つ考えてみませんか?
2: 元のデザインに何か問題があると思いますか? それを修正するためにあなたは何をしますか?
3: このようなパターンに遭遇したことがありますか? 私のコード全体でかなり一般的です。Time
ただし、実際にはポリモーフィックであり、ヒープが割り当てられているため、一般的にはこれは問題ではありません。
4: 問題の根本に戻ると、「移動する必要はありません。移動できないオブジェクトをその場で作成したいだけですが、コンパイラはそうすることができません」なぜないのですか? C ++での簡単な解決策と、別の言語での解決策はありますか?
c++ - 値で一時的に渡すときに移動の省略を回避するにはどうすればよいですか?
次のコードでは:
Widget オブジェクトは常にインプレース (foo 関数内) で構築されるため、move 構築は行われません (少なくとも私が試したすべてのコンパイラで)。move の構築が実際に行われる方法で一時的な値を関数に渡す簡単な例は何ですか?