移动构造函数不会隐式地为成员变量工作?

时间:2011-05-12 09:50:51

标签: c++11 move-constructor

为什么不这样:(vs2010)在类中移动向量?

#include <vector>

class MoveTest
{
public:
    std::vector<int> m_things;
};

int _tmain(int argc, _TCHAR* argv[])
{
    MoveTest m;
    m.m_things.push_back(12);

    MoveTest m2 = std::move(m);
    // std::vector has been copied, not moved

    return 0;
}

这是否意味着每个使用std :: vector(以及其他可移动类)的类都应该有一个显式的移动构造函数和赋值?

4 个答案:

答案 0 :(得分:9)

除了已经提供的关于这些规则的迟到与vs2010发布时相比的好答案之外,

隐式生成的移动构造函数的规则是:

  

如果X类的定义有   没有明确宣布一个举动   构造函数,一个将隐式   当且仅当

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

隐式生成的移动赋值运算符的规则遵循上述模式。

隐式生成复制构造函数的规则稍微改变了

  

如果类定义没有   显式声明一个复制构造函数,   一个被隐含地宣布。如果   类定义声明了一个动作   构造函数或移动赋值   运算符,隐式声明的副本   构造函数定义为已删除;   否则,它被定义为默认   (8.4)。后一种情况已被弃用   如果类具有用户声明的副本   赋值运算符或用户声明的   析构函数。

类似地,对于复制赋值运算符:

  

如果类定义没有   明确声明副本分配   运算符,一个是隐式声明的。   如果类定义声明了一个   移动构造函数或移动赋值   运算符,隐式声明的副本   赋值运算符定义为   删除;否则,它被定义为   违约(8.4)。后一种情况是   如果班级有,则弃用   用户声明的复制构造函数或   用户声明的析构函数。

底线:3的规则现在是5的规则。您可以忽略全部5(如果默认行为适合您),或者您需要考虑(并可能定义)所有5:

  1. 复制构造函数
  2. 复制作业
  3. 移动构造函数
  4. 移动作业

答案 1 :(得分:7)

使用完全符合C ++ 0x编译器,您的类将具有移动成员的隐式移动构造函数,以及隐式复制构造函数。在此示例中,将使用隐式移动构造函数。

但是,在委员会同意此规则之前,MSVC2010已经出现,因此您必须明确地编写移动构造函数。然后,您还需要定义默认构造函数和复制构造函数,并且可能还应该定义移动赋值和复制赋值以获得良好的度量:

class MoveTest
{
public:
    std::vector<int> m_things;

    MoveTest()
    {}

    MoveTest(MoveTest&& other):
        m_things(std::move(other.m_things))
    {}

    MoveTest(MoveTest const& other):
        m_things(other.m_things)
    {}

    MoveTest& operator=(MoveTest&& other)
    {
        MoveTest temp(std::move(other));
        std::swap(*this,temp);
        return *this;
    }

    MoveTest& operator=(MoveTest const& other)
    {
        if(&other!=this)
        {
            MoveTest temp(other);
            std::swap(*this,temp);
        }
        return *this;
    }

};

答案 2 :(得分:2)

MoveTest类没有移动构造函数,因此它使用了默认的复制构造函数。

复制构造函数复制成员元素。 : - )

可能存在C ++ 11 conformat编译器生成默认移动构造函数的情况,但我不确定最终规则的结束位置(存在很晚的更改)。 VS2010太老了,也不知道。

答案 3 :(得分:1)

VS2010没有隐式移动构造函数。你必须明确地写一个。