右辺値参照(&&) ユニバーサル参照の強みがよくわかりません
これらに関していくつか記事を調べたんですがどうもしっくりきません
かみ砕いた説明してくださる方おりましたら是非教えていただきたいです!
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/05/16 06:36 編集
回答4件
0
ベストアンサー
rvalue referenceが導入される前夜のC++を考えてみます。
その頃存在したreferenceはこんにちのlvalue referenceのことでした。
const lvalue referenceはlvalue以外にもrvalueも束縛できました。
さて、rvalueですが、最終的に変数に代入するか変数を初期化するかのいずれかに用いることが基本的には多いため、「一時的なもの」という共通認識が醸造されていました。
ここで新たに次のような社会的合意を行いました。それは「rvalueは所有権をもたない」というものです。
所有権を持たないならば対象オブジェクトをいかに書き換えようとも文句は言われない。つまりここで、rvalue referenceで受け取ったものは自由にいじくり回していい、という社会的合意を行うわけです。
さて、「rvalueは所有権をもたない」を前提にさらに新たな社会的合意が行なえます。それがmove sematicsです。所有権を持たないオブジェクトのポインタは掠め取ってもよいという社会的合意を行ったわけです。
さて、こうなると困るのがlvalueとrvalueどちらを束縛しているか言語仕様上判別困難という問題です。そこでrvalue referenceというものを導入し、オーバーロード解決ではrvalue referenceはconst lvalue referenceより優先されるとしました。このrvalue refernceの導入によってmove sematicsに対する言語面からのサポートが追加されたことになります。
ではここで新たな問題が出ます。lvalueもrvalueも受け取るけど、rvalueに対してはmove sematicsを適用したい、という需要です。
これに対して言語仕様としてUniversal Refernceが追加されました。template関数の引数の型をT&&にようにしたとき、これはrvalue refenreceではなくuniversal referneceとなります。
これの挙動は割愛しますがこれによってperfect forwardingという技法が可能となりました。もっぱらperfect forwardingのために使うため、forwarding referenceとも呼ばれます。
詳しい内容は
みんなlvalueとrvalueを難しく考えすぎちゃいないかい? - Qiita
へ
オペレーターが足りないので &&が発明されたのでしょうか?
&&はそもそもオペレーターではありません。
投稿2021/05/16 11:11
総合スコア5852
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
皆様の回答に対して蛇足になりますし、質問者さんのレベルより若干難しくなってしまうかもしれませんが。。。
「ムーブセマンティクス」の前に「例外安全性」を理解したほうが良いように思います。
例外安全と例外中立
上記を理解したうえで、rvalue referenceを使わずにno-fail保証や強い保証を担保したコード(特にライブラリ)を書こうとすると、文法上の制約がとても強くて、書くのが大変だったり、自然な書き方が出来ないことが実感できると思います。
例外安全性は、C#等の例外機構があるプログラミング言語全般に共通するとても重要な概念ですので、しっかり勉強しておくことをお勧めします。
投稿2021/05/17 00:17
総合スコア171
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
参考にしたというページに書いてあることが初心者向けにはほぼ完ぺきといってくらい完成度の高いものです。 きちんとした理解をするにあたって付け加えることも無駄なこともありません。 理解できていないのはおそらくレイヤを分けて考えられていないからです。
右辺値参照は「左辺値と区別できる」ということしかありません。 それ単体では良くも悪くもなく、どう使うかはあなた次第です。
しかし一般的な用途としてはムーブセマンティクスという考え方が導入されていて、データを移動 (move) するか複製 (copy) するかを状況によって使い分けることで (複製しなくてよいときに複製を避けることで) 効率が良くなるという使い方がされています。 どちらにすべき状況なのかという区別のために右辺値なのか左辺値なのかを用いているわけです。
「移動」をどのように実現するかもあなた次第ですが典型的な方法としては内部でポインタを交換するという方法がよく用いられているようですね。
投稿2021/05/16 08:48
総合スコア5686
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/05/16 09:50
2021/05/16 11:01
0
copy と move の違い、ですか?
C++
1#include <iostream> 2#include <algorithm> 3#include <numeric> 4 5class foo { 6 int* data_; 7 int n_; 8public: 9 foo(int n) : n_(n) { data_ = new int[n]; std::iota(data_, data_+n_,0); } 10 ~foo() { delete[] data_; } 11 12 // other から *this への"複製" 13 foo(const foo& other) : n_(other.n_) { 14 std::cout << "copy\n"; 15 data_ = new int[n_]; 16 std::copy(other.data_, other.data_ + n_, data_); 17 } 18 19 // other から *this への"移動" 20 foo(foo&& other) : n_(other.n_) { 21 std::cout << "move\n"; 22 data_ = other.data_; // newせず、 23 other.data_ = nullptr; // otherから横取り 24 } 25 26 void print() const { 27 for ( int i = 0; i < n_; ++i ) std::cout << data_[i] << ' '; 28 std::cout << std::endl; 29 } 30}; 31 32int main() { 33 foo src(5); 34 35 foo copied(src); copied.print(); 36 foo moved(std::move(src)); moved.print(); 37}
右辺値参照使ってmoveすると新たな領域確保と複製を行わないのでその分速い。
投稿2021/05/16 08:43
総合スコア16612
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。