当未明确使用std :: move时,c ++ 11何时会自动执行?

kee*_*lar 6 c++ lvalue rvalue-reference move-semantics c++11

如果我有一个struct我没有提供任何副本和移动构造函数:

struct MyStruct {
  MyStruct() { // this is the only function
    ...
  }
  ...
};
Run Code Online (Sandbox Code Playgroud)

那么如果我做以下事情:

std::vector<MyStruct> vec;
...
vec.push_back(MyStruct());
Run Code Online (Sandbox Code Playgroud)

而不是使用std::move()如下:

vec.push_back(std::move(MyStruct()));
Run Code Online (Sandbox Code Playgroud)

c ++ 11会巧妙地为我的临时变量做些什么吗?或者,我怎样才能确定它是移动而不是副本?

dus*_*yle 10

在C++ 11中,std::vector::push_back如果传递了一个rvalue(并且该类型存在移动构造函数),它将使用移动构造函数,但是你也应该考虑std::vector::emplace_back在这种情况下使用; std::vector::emplace_back将构造对象而不是移动它.

  • 目前的答案是误导.对于要使用的"移动构造函数",类型首先需要有一个.这不仅仅是传递右值引用的问题. (3认同)
  • 它应该说"如果交了右值".引用变量的类型,而不是表达式. (2认同)

jua*_*nza 7

c ++ 11会巧妙地为我的临时变量做些什么吗?或者,我怎样才能确定它是移动而不是副本?

这取决于.这个

vec.push_back(MyStruct());
Run Code Online (Sandbox Code Playgroud)

将绑定到

std::vector<MyStruct>::push_back(MyStruct&&);
Run Code Online (Sandbox Code Playgroud)

但是,传递的右值是否被移动或复制完全取决于是否MyStruct具有移动复制构造函数(同样用于移动赋值).

如果你打电话,它将完全没有区别

vec.push_back(std::move(MyStruct()));
Run Code Online (Sandbox Code Playgroud)

因为MyStruct()已经是右值了.

所以它真的取决于细节MyStruct.你的问题中根本没有足够的信息来知道你的班级是否有移动构造函数.

这些是类具有隐式生成的移动构造函数必须满足的条件:

  • 没有用户声明的副本构造函数
  • 没有用户声明的副本赋值运算符
  • 没有用户声明的移动赋值运算符
  • 没有用户声明的析构函数

当然,如果不满足以下任何条件,您可以随时提供自己的条件:

MyStruct(MyStruct&&) = default;
Run Code Online (Sandbox Code Playgroud)

  • 我认为`push_back`调用将始终绑定到`std :: vector <MyStruct> :: push_back(MyStruct &&);`用于rvalue.但是,如果没有可用的移动构造函数,向量中新元素的构造将回退到`push_back`中的复制文件(如果显式删除了移动文件,则会变为格式错误). (2认同)

Sci*_*cis 5

因为MyStruct()将创建一个右值,T &&所以将调用重载。

实际上很容易验证(demo):

#include <iostream>
struct A{ int x; };

void  foo(A &&x){ std::cout<<"&&" <<std::endl; }

void  foo(A &x){ std::cout<<"&" <<std::endl; }

int main() {
    foo(A()); // prints &&
    A a;
    foo(a); // prints &
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

澄清一下:我没有提到任何有关移动构造函数的内容,因为可以显式删除移动构造函数,但仍然T &&会调用它。

例如(演示):

#include <iostream>
struct A{ int x; A() = default; A(const A& ) = default; A(A&&) = delete; };
/*                                                                  ^
                                                            no move ctor */
void  foo(A &&x){ std::cout<<"&&" <<std::endl; }

void  foo(A &x){ std::cout<<"&" <<std::endl; }

int main() {
    foo(A()); //still prints &&
    A a;
    foo(a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如我之前所说,这是因为它是一个右值......