我可以在没有提供移动构造函数的类中使用std :: move吗?

时间:2018-05-30 16:35:12

标签: c++ c++11 move move-semantics

我有一个这样的课程:

class myClass
{
    int x[1000];
 public:
     int &getx(int i)
    {
        return x[i];
    }
}

请注意,我这里没有提供移动构造。

如果我使用以下代码:

myClass A;
auto B=std::move(a);

A移动到B还是因为我没有提供移动构造函数,A被复制到B?

是否有对象的默认移动构造函数?如果是,它如何使用指针和动态分配的数组?

5 个答案:

答案 0 :(得分:2)

虽然您没有提供显式移动构造函数,但编译器为您提供了隐式移动构造函数。

  

如果类X的定义没有显式声明一个移动构造函数,那么当且仅当

时,才会隐式声明一个默认值。      
      
  • X没有用户声明的复制构造函数,
  •   
  • X没有用户声明的复制赋值运算符
  •   
  • X没有用户声明的移动赋值运算符
  •   
  • X没有用户声明的析构函数,
  •   
  • 移动构造函数不会被隐式定义为已删除。
  •   

所以你问题的答案是:不,A不会复制到B。

目前尚不清楚您在其他问题中提出的问题。请详细说明。

答案 1 :(得分:0)

为您的类生成移动构造函数,因为您没有定义任何避免生成它的方法(如用户定义的析构函数或复制构造函数)

自动生成的移动构造函数将移动每个成员。对于int[1000],它等同于复制。

答案 2 :(得分:0)

您的问题与this one类似。请注意,std :: move只是一个强制转换。您的值 a 将被转换为右值引用,但在您的情况下,原始对象不会被掠夺或被盗。

要正确使用API​​或习惯用法,您必须将其用于正确的事情。移动对于例如移动最有意义类对象,其中大量对象数据在堆上分配。这样的物体很容易被盗,并且“移动”可以使被盗物体处于明确定义的状态。规范的例子可以是例如某种类型的字符串类,在堆上有字符串数据。

在你的情况下,你想要发生什么?假设 a 是某个函数中的局部变量,即假设 a 在堆栈中。假设 b 是全局或文件范围或匿名命名空间变量,即不在堆栈上。从 a 移动到 b 时,您希望发生什么?

对于一个字符串,盗窃是有道理的。对于你的情况,盗窃是荒谬的。

答案 3 :(得分:0)

  

如果没有为类类型(struct,class或union)提供用户定义的移动构造函数,并且满足以下所有条件:

     
      
  • 没有用户声明的副本构造函数。
  •   
  • 没有用户声明的复制赋值运算符。
  •   
  • 没有用户声明的移动分配操作符。
  •   
  • 没有用户声明的析构函数
  •   
     

然后编译器将一个移动构造函数声明为其类的非显式内联公共成员,其签名为T :: T(T&&)。

来自cppreference

基本上,只要您没有定义复制构造函数,复制赋值重载,移动赋值重载或析构函数,就会创建默认移动构造函数。否则,您必须自己定义行为或使用: class_name ( class_name && ) = default; 它将显式声明移动构造函数的默认版本。

答案 4 :(得分:0)

  

是否有对象的默认移动构造函数?

在您的情况下是的。对于任何类型T,只有在满足某些条件时才会隐式声明移动构造函数。有关详细信息,请参阅cpperference.com

  

如果是,它如何使用指针和动态分配的数组?

默认实现将生成指针的浅表副本。因此,多个对象将指向动态分配的数组。这将导致问题。有关此主题的更多信息,请参阅The Rule of Three

如果指针指向动态分配的数组,则需要:

  1. 提供一个显式定义的复制构造函数,它使用动态分配的数组做正确的事情。这样做的副作用是将隐式删除默认移动构造函数。和/或
  2. 提供明确定义的移动构造函数,您可以在其中适当地移动动态分配的数组的所有权。