左辺値(Lvalue)#
左辺値は、メモリ上に明確な位置を持つオブジェクトであり、アドレスを取ることができます。つまり、左辺値は代入演算子の左側に現れる式です。例えば、変数、配列の要素、ポインタの参照などが左辺値です。
特徴:
- アドレスを取ることができる:左辺値式の結果はオブジェクトであり、アドレス演算子
&
を使用してそのオブジェクトのアドレスを取得することができます。 - 永続性:左辺値で表されるオブジェクトは、式の評価が終了した後も存在し続けます。ただし、スコープ外に出たり、明示的に破棄されるまでです。
例:
int x = 10;
int *p = &x;
*p = 20;
右辺値(Rvalue)#
右辺値は、式の評価時に作成される一時オブジェクトを指します。通常、明確なメモリ位置を持たず、アドレスを取ることはできません。右辺値は通常、定数、一時オブジェクト、または戻り値です。
特徴:
- アドレスを取ることはできない:右辺値は固定されたメモリ位置を持たないため、右辺値のアドレスを取ることはできません。
- 一時性:右辺値で表されるオブジェクトは、式の評価が終了した後は存在しません。
例:
int y = 5 + 3;
int z = y * 2;
右辺値参照(Rvalue Reference)の導入#
C++11 では、右辺値参照が導入され、右辺値をより効率的に操作するために使用されます。右辺値参照は&&
を使用して宣言されます。右辺値をより効率的にキャプチャし、操作するための方法を提供し、不要なコピーと移動操作を減らすことができます。
右辺値参照の応用:
- ムーブセマンティクス(Move Semantics):ムーブコンストラクタとムーブ代入演算子を使用することで、リソースの所有権を移動することができます。
- 完全転送(Perfect Forwarding):テンプレート関数で右辺値参照と
std::forward
を使用することで、引数の完全転送を実現することができます。
例:
class A {
public:
A() { std::cout << "コンストラクタ" << std::endl; }
A(const A&) { std::cout << "コピーコンストラクタ" << std::endl; }
A(A&&) { std::cout << "ムーブコンストラクタ" << std::endl; }
};
void foo(A&& a) {
A b = std::move(a); // ムーブコンストラクタが呼ばれる
}
int main() {
A a;
foo(std::move(a)); // aを右辺値参照に変換
return 0;
}
std::move(a)
は左辺値a
を右辺値参照に変換し、コピーではなくムーブコンストラクタを呼び出すため、不要なコピーが減り、効率が向上します。