序文
std::move() の本来のセマンティクスはlvalue を rvalue に変更することであり、これ自体にはコピー構築の呼び出しや移動構築の呼び出しは含まれません。std::move() を使用して移動コンストラクターを呼び出すという幻想を持たないでください。たとえば、次の例では、 std::move() は値を左辺値から右辺値に変更するためにのみ使用されており、コピーとは何の関係もありません。
void foo(Test &&t) {
}
template <typename T>
void fun(T &&v) {
}
int main() {
Test t1;
// foo(t1); //编译错误,不能绑定左值
foo(std::move(t1)); //将左值变为右值,编译通过
Test t2;
fun(t2); //编译通过,但不涉及到拷贝
fun(std::move(t2)); //编译通过,也不涉及到拷贝
return 0;
}
したがって、コピーする場合は、最初に値で渡す必要があります。つまり、A を B にコピーする必要があります。この時点で、A が左辺値の場合はコピー コンストラクターのみを呼び出すことができ、A が右辺値の場合はコピー コンストラクターのみを呼び出すことができます。 move を呼び出すことができる コンストラクタについてはプログラマが自分で判断できる 左辺値を別の変数にコピーして使い物にならない場合は、コピーした場所に std::move(A) を記述すればよい。
一般に、次のような状況があります。
容器に入れる
std::vector<Test> vec;
vec.reserve(10);
Test t1;
vec.push_back(t1); //Copy Constructor....
Test t2;
vec.push_back(std::move(t2)); //Move Constructor...
移動すると、移動されたオブジェクトが変更されることに注意してください。移動されたオブジェクトが const の場合でも、コピー コンストラクターが呼び出されます。
関数の引数リスト
void foo(Test t) {
}
int main() {
Test t1;
foo(t1); //Copy Constructor....
Test t2;
foo(std::move(t2)); //Move Constructor....
return 0;
}
関数の戻り値
Test foo() {
std::vector<Test> vec;
vec.resize(1);
return vec.front(); //Copy Constructor....
}
Test fun() {
std::vector<Test> vec;
vec.resize(1);
return std::move(vec.front()); //Move Constructor....
}
int main() {
foo();
fun();
return 0;
}
高度
ユニバーサル参照 + 完全転送を使用して、lvalue-copy と rvalue-move のセマンティクスを実現します。
35 class Other {
36 public:
37 template <typename T>
38 Other(T &&t) : t_{std::forward<T>(t)} {
41 }
42 private:
43 Test t_;
44 };
45 int main() {
46 Test t;
47 Other o1(t); //拷贝
49 Other o2(std::move(t)); //移动
50 return 0;
51 }