https://cpplover.blogspot.com/2009/11/rvalue-reference_23.html
上記をよく見て勉強しよう。
キーワードを抜粋。
- lvalueとは、明示的に実体のある、名前付きのオブジェクトであり、rvalueとは、一時的に生成される無名のオブジェクトである。
struct X{};
int f() { return 0; }
int main()
{
int i = 0;
i; // lvalue
0; // rvalue
X x;
x; // lvalue
X(); // rvalue
f(); // rvalue
}- lvalueはrvalueに変換できるが、その逆は不可。
なお、関数の仮引数はlvalueなので、const参照でない限りrvalueは受け取れない。(若干不安。要確認)
lvalue reference
C++98のreferenceは、C++11においては、lvalue referenceと呼ばれる。
struct X{ } ;
void f( X & ) { }
void g( X const & ) { }
int main()
{
X x;
f( x ); // 1. OK
f( X() ); // 2. Error
g( X() ); // 3. OK
}rvalue reference
rvalue referenceとは、rvalueに対する参照。アンパサンドを二つ使って表現する。
struct X{ };
int main()
{
X x;
// lvalue reference
X & lr1 = x; // 1. OK
X & lr2 = X(); // 2. Error
// rvalue reference
X && rr1 = x; // 3. Error
X && rr2 = X(); // 4. OK
}サンプル:右辺値参照の仮引数を受け取る関数の呼び出し
#include <iostream>
#include <vector>
struct X{ };
void funcB(X&& rr){
std::vector<X> a;
a.emplace_back(rr); // OK Xのコピーコンストラクタが呼ばれる
a.emplace_back(std::move(rr)); // OK ただし、Xのムーブコンストラクタが呼ばれる
return;
}
void funcA(X&& rr){
//funcB(rr); // Error ビルドが通らない
funcB(std::move(rr)); // OK
}
int main()
{
X x;
funcA(x); // Error ビルドが通らない
funcA(std::move(x)); // OK
}結論をまとめると、右辺値参照を受け取れる関数を呼び出す際は、std::move()が必要。
ただし、std::vectorのemplace_backはstd::move()で渡さない方がいいかも?
ということ。
emplace_backは複数の仮引数が定義されているので、コピーコンストラクタかムーブコンストラクタが呼ばれるという挙動の違いにつながる。
↓
emplace_backの挙動は
にまとめる。
コメントを残す