std::move() 注意事項

序文

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 }

 

おすすめ

転載: blog.csdn.net/cyfcsd/article/details/129996342