問題タブ [rvalue-reference]

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.

0 投票する
2 に答える
433 参照

c++ - 戻り値の自動変数のコピー省略

C++0xの「12.8クラスオブジェクトのコピーと移動[class.copy]段落31」コピーの省略が発生した場合、正確には次のようになります。

特定の基準が満たされると、実装はクラス オブジェクトのコピー/移動の構築を省略できます [...]。コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます [...]:

  • クラスの戻り値の型を持つ関数の return ステートメントで、式が関数の戻り値の型と同じ cv-unqualified 型を持つ不揮発性の自動オブジェクト [...] の名前である場合、コピー/移動操作は可能です。自動オブジェクトを関数の戻り値に直接構築することで省略可能
  • [...]

そして今、これにより次のコードでコピーを回避できるかどうか疑問に思います

それとも、そのルールは例に当てはまらないので、明示的に行う必要がありますか?

私の意図は、明らかなReturn Value Optimization (RVO)ifを排除することであったことに注意してください。

それとも、ここで完全に間違った方向に進んでいますか? 右辺値参照を使用できるreturnmoveに関連する変更がありましたよね?

0 投票する
2 に答える
323 参照

c++ - 複合オブジェクトを構築するときに不要なコピーを排除する

名前付きパラメーターコードを開発することを考えていましたが、次のようなコードを考えるようになりました。

これを単純に実装すると、最初に「make_pair(4,5)」を実行し、次に結果を「make_pair(3、...)」の2番目の要素にコピーしてから、「make_pair」の2番目の要素にコピーします。 (2、...)」など。

これにより、残念ながらO(n ^ 2)のパフォーマンスが発生し、不要なコピーが多数発生します。ここでも、(名前付きの)戻り値の最適化がどのように役立つかわかりません。

理想的には、それがの最後の場所にあることをmake_pair(4,5) 認識xし、その場所に自分自身を構築します。

これをさらに進める:

このようなコードのコピーも避けたいです。

この最適化は非常に明白なので、コンパイラーがそれを実行すると想定する必要がありますか、それともコピーを回避するためにこれをコーディングする別の方法がありますか?

0 投票する
1 に答える
500 参照

c++ - 右辺値でのキャプチャは許可するが代入は許可しない演算子のオーバーロード

operator+設計することは可能ですか?また、これを可能にするためにクラスCをオーバーロードするにはどうすればよいですか?

しかし、これは不可能です:

編集: オブジェクトを小文字に変更しました。c1c2およびcクラスのオブジェクトですC&&論理operator&&ではなく、右辺値参照です。

たとえば、次のように記述します。

は 100% 適切な (新しい) C++ コードですが、

明らかにコンパイルエラーです。私はまったく同じことを望んでいますが、代わりに double の、私の class C.

2 番目の編集: 演算子が C または C& を返した場合、右辺値参照への割り当てだけでなく、c1 + c2 への割り当ても行うことができますが、これは無意味です。ここで const を指定すると無効になりますが、右辺値への代入も無効になります。少なくとも VC++ 2k10 では。では、これはどのくらい2倍になるのでしょうか?

0 投票する
6 に答える
6782 参照

c++ - 5のルールを実際に実装するにはどうすればよいですか?

一番下のUPDATE

q1:かなり重いリソースを管理するクラスに 5 のルールをどのように実装しますか? その使用法を大幅に簡素化して美しくするために、値によって渡す必要がありますか? それとも、ルールの 5 つの項目すべてが必要ではないでしょうか?

実際には、画像が通常 128*128*128 double である 3D イメージングで何かを始めています。このようなものを書くことができれば、数学はずっと簡単になります:

q2: copy elision / RVO / move セマンティクスの組み合わせを使用すると、コンパイラは最小限のコピーでこれを実行できるはずですよね?

これを行う方法を理解しようとしたので、基本から始めました。コピーと割り当てを実装する従来の方法を実装するオブジェクトを想定します。

ここで右辺値を入力し、セマンティクスを移動します。私が知る限り、これは実用的な実装になるでしょう:

ただし、コンパイラ (VC++ 2010 SP1) はこれにあまり満足しておらず、コンパイラは通常正しいです。

q3:これを解決するにはどうすればよいですか? AnObject& operator = ( const AnObject& rh ) に戻ると確かに修正されますが、かなり重要な最適化の機会を失っていませんか?

それとは別に、move コンストラクターと代入のコードが重複していることは明らかです。したがって、今のところあいまいさを忘れて、コピーとスワップを使用してこれを解決しようとしますが、今度は右辺値を使用します。ここで説明したように、カスタム スワップは必要なく、代わりに std::swap にすべての作業を任せることができます。これは非常に有望に思えます。そこで、std::swap が move コンストラクターを使用して一時的に構成をコピーし、それを *this と交換することを期待して、次のように書きました。

しかし、それはうまくいかず、 std::swap が演算子 = ( AnObject&& rh ) を再度呼び出すため、無限再帰によるスタック オーバーフローが発生します。q4:誰かがその例で何を意味するかの例を提供できますか?

これは、2 番目の swap 関数を提供することで解決できます。

これでコードの量はほぼ 2 倍になりましたが、その移動部分はかなり安価な移動を許可することで報われます。しかし一方で、通常の代入はもはやコピー省略の恩恵を受けることができません。この時点で、私は本当に混乱しており、何が正しくて何が間違っているのかわからなくなっているので、ここで何らかの情報を得たいと思っています..

更新したがって、2つのキャンプがあるようです。

  • 移動代入演算子をスキップして、C++03 で教えられたこと、つまり、引数を値で渡す単一の代入演算子を作成することを続行するようにというものです。
  • もう1つは、移動代入演算子を実装し(結局のところ、現在はC ++ 11です)、コピー代入演算子に引数を参照渡しさせるように言っています。

(わかりました、そしてベクトルを使用するように私に言っている3番目のキャンプがありますが、それはこの架空のクラスの範囲外です。実際には私はベクトルを使用し、他のメンバーもいるでしょうが、ムーブコンストラクタ/割り当ては自動的に生成されません (まだ?) 質問はまだ保持されます)

残念ながら、このプロジェクトは開始されたばかりであり、データが実際にどのように流れるかはまだわかっていないため、実際のシナリオで両方の実装をテストすることはできません。そのため、単純に両方を実装し、割り当てなどのカウンターを追加して、約 2 回の反復を実行しました。このコードで、T は実装の 1 つです。

このコードは、私が求めているものをテストするのに十分ではないか、コンパイラがあまりにも賢すぎる: arraySize と numIter に何を使用しても、両方の陣営の結果はほとんど同じです: 同じ数の割り当て、タイミングにわずかな変動がありますが、再現可能な有意差はありません。

したがって、誰かがこれをテストするためのより良い方法を指摘できない限り (実際の使用シナリオがまだわかっていないことを考えると)、それは問題ではなく、したがって開発者の好みに任されていると結論付けなければなりません。その場合、私は#2を選びます。

0 投票する
4 に答える
5734 参照

c++ - R値参照とコード重複のオーバーロード

次のことを考慮してください。

r値参照のおかげで、operator +のこれらの4つのオーバーロードにより、一時的なものを再利用することで、作成されるオブジェクトの数を最小限に抑えることができます。しかし、これがもたらすコードの重複は好きではありません。より少ない繰り返しで同じことを達成できますか?

0 投票する
2 に答える
587 参照

c++ - 値によって返されるときに、値パラメーターは暗黙的に移動されますか?

次の関数について考えてみます。

return xコピーコンストラクターまたは移動コンストラクターを呼び出しますか?(ここでNRVOを脇に置いておきましょう。)

調査するために、Foo移動可能でコピー可能ではない単純なクラスを作成しました。

値パラメーターを値で返すときにmoveコンストラクターが呼び出された場合は、すべて問題ないはずです。return xしかし、現在のg ++​​コンパイラは、次のエラーメッセージで文句を言います。

に置き換えるreturn xreturn std::move(x)、すべて問題ありません。このことから、必要に応じて、値パラメーターからの移動を明示的に実行する必要があると結論付けます。g ++の動作は準拠していますか?

0 投票する
1 に答える
2263 参照

c++ - 移動可能なオブジェクトが最後に使用されたときに、コンパイラは自動的に移動セマンティクスを使用しますか?

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

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

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

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

質問:

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

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

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

0 投票する
2 に答える
162 参照

c++11 - この不自然な例で移動コンストラクターが呼び出されないのはなぜですか?

GetPerson からの名前のない戻り値をムーブ コンストラクターにバインドするべきではありませんか?

人.hpp

main.cpp

私は gcc バージョン 4.4.3 (Ubuntu 4.4.3-4ubuntu5) を使用しており、次のようにコンパイルしています。

RVOまたはNRVOが原因ですか?

0 投票する
5 に答える
3374 参照

c++ - 右辺値関数のオーバーロード

関数をオーバーロードして、何らかの方法で引数を操作してから引数への参照を返すようにしたいのですが、引数が変更可能でない場合は、代わりに引数の操作されたコピーを返す必要があります。何年もの間それをいじった後、これが私が思いついたものです。

このコードは正しく機能しているようですが、誰かがそれを行うためのより良い方法を考えられるかどうか聞いてみたいです。

テストプログラムは次のとおりです。

正しい出力は

私がこれを行うことができれば、それは少しきれいになると思います:

もちろん、へのほとんどの関数呼び出しはfooあいまいであるため、それは機能しません–呼び出しfoo自体を含みます!しかし、どういうわけかコンパイラに最初のものを優先するように指示できれば...

私が言ったように、私が投稿したコードは正しく機能します。私がそれについて気に入らない主なことは、繰り返しの余分なコードです。私がそのような機能をたくさん持っていたら、それはかなり混乱し、そのほとんどは非常に繰り返しになるでしょう。fooそれで、私の質問の2番目の部分として、2番目と3番目の関数のコードを自動的に生成する方法を誰かが考えることができますか?例えば

0 投票する
3 に答える
830 参照

c++ - 移動操作の条件付きコンパイル

コンパイラが右辺値参照をサポートしているかどうかを確認するにはどうすればよいですか?標準のプリプロセッサマクロはありますか、それとも異なるコンパイラには異なるマクロがありますか?理想的には、これを書きたいと思います。