質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

3721閲覧

右辺値参照(&&) ユニバーサル参照の強み

apa

総合スコア68

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/05/16 06:01

右辺値参照(&&) ユニバーサル参照の強みがよくわかりません
これらに関していくつか記事を調べたんですがどうもしっくりきません
かみ砕いた説明してくださる方おりましたら是非教えていただきたいです!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/05/16 06:16

読んだ記事と、どのような点に納得がいかなかったのかをご提示いただけないでしょうか? (同じものを再提示だけになる可能性もあります)
guest

回答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

yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

皆様の回答に対して蛇足になりますし、質問者さんのレベルより若干難しくなってしまうかもしれませんが。。。

「ムーブセマンティクス」の前に「例外安全性」を理解したほうが良いように思います。
例外安全と例外中立

上記を理解したうえで、rvalue referenceを使わずにno-fail保証や強い保証を担保したコード(特にライブラリ)を書こうとすると、文法上の制約がとても強くて、書くのが大変だったり、自然な書き方が出来ないことが実感できると思います。

例外安全性は、C#等の例外機構があるプログラミング言語全般に共通するとても重要な概念ですので、しっかり勉強しておくことをお勧めします。

投稿2021/05/17 00:17

ttact

総合スコア170

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

参考にしたというページに書いてあることが初心者向けにはほぼ完ぺきといってくらい完成度の高いものです。 きちんとした理解をするにあたって付け加えることも無駄なこともありません。 理解できていないのはおそらくレイヤを分けて考えられていないからです。

右辺値参照は「左辺値と区別できる」ということしかありません。 それ単体では良くも悪くもなく、どう使うかはあなた次第です。

しかし一般的な用途としてはムーブセマンティクスという考え方が導入されていて、データを移動 (move) するか複製 (copy) するかを状況によって使い分けることで (複製しなくてよいときに複製を避けることで) 効率が良くなるという使い方がされています。 どちらにすべき状況なのかという区別のために右辺値なのか左辺値なのかを用いているわけです。

「移動」をどのように実現するかもあなた次第ですが典型的な方法としては内部でポインタを交換するという方法がよく用いられているようですね。

投稿2021/05/16 08:48

SaitoAtsushi

総合スコア5466

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

apa

2021/05/16 09:50

返信ありがとうございます Moveが T&& なのはわかっております 説明的にいくとMoveを使うために &&が発明されたという考えであっていますでしょうか?
SaitoAtsushi

2021/05/16 11:01

レイヤを分けて考えられていないと指摘したのはそういうところです。 右辺値参照と左辺値参照の区別が無かったとしてもムーブの考え方はありえますし、一方では右辺値参照と左辺値参照の区別があればムーブとコピーの区別を自動化できて便利だというのも確かです。 強く連携はします (おそらくそれを想定して言語設計されてもいる) けども独立した概念なので分けて考えた上でどのように関連してくるのか個別に理解すべきことであって「ために」かそうでないかという二択で考えられることではありません。
guest

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

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

apa

2021/05/16 09:51

返信ありがとうございます MoveとCopyの違いは理解しているつもりです オペレーターが足りないので &&が発明されたのでしょうか?
episteme

2021/05/16 11:05 編集

右辺値参照か否か、区別がつかんと効率的な実装できんじゃないですか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問