C++がすごく進化しているみたいなので少し調べてみた。
・右辺値参照 T&&
まず右辺値とは代入できない式のこと。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
int a; int func() { return 0; } int _tmain() { int a; int b; a = 1; a = b; b = func(); 1 = a; // error a + b = 1; //error func() = a; //error } |
この例では、下2つが右辺値に代入しているのでエラーになる。
いままでのC++の参照には左辺値右辺値の区別がなかった。右辺値の定義をもう少し進めると&や*でアドレスが取得できない式であることがわかる。そしてC++の参照には右辺値を設定することはできない。
以下のコードを考える。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include "stdafx.h" #include <memory.h> using namespace std; struct DATA { DATA() { p = new int[1000]; } ~DATA() { delete[] p; } DATA& operator=(const DATA& rhs) { delete[] p; p = new int[1000]; memcpy(p, rhs.p, 1000*sizeof(int)); return *this; } int* p; }; DATA func() { return DATA(); } int _tmain(int argc, _TCHAR* argv[]) { DATA data1; DATA data2; data1 = data2; data1=func(); return 0; } |
data1=data2では本当にコピーしないといけないが、data1=func()のときはポインタだけコピーすればいい。
そこで右辺値参照を使って以下のように書いてみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include "stdafx.h" #include <memory.h> using namespace std; struct DATA { DATA() { p = new int[1000]; } ~DATA() { delete[] p; } DATA& operator=(const DATA& rhs) { delete[] p; p = new int[1000]; memcpy(p, rhs.p, 1000*sizeof(int)); return *this; } DATA& operator=(DATA&& rhs) { p = rhs.p; rhs.p = NULL; return *this; } int* p; }; DATA func() { return DATA(); } int _tmain(int argc, _TCHAR* argv[]) { DATA data1; DATA data2; data1 = data2; data1=func(); return 0; } |
data1=func()のときは右辺値参照が引数となったoperator=()が呼ばれる。
data1 = data2のときも右辺値参照で呼びたいときにはmove()を使う
1 |
data2 = std::move(data1); |