移动构造函数是自动生成的,即使成员没有移动构造函数?

时间:2017-06-21 17:58:14

标签: c++ c++11 constructor

引自 C ++ Primer

  

如果我们明确要求编译器生成移动操作   使用= default,编译器无法移动所有   成员,然后移动操作将被定义为已删除

     

移动构造函数定义为已删除如果   class有一个定义自己的复制构造函数的成员,但也没有   定义移动构造函数,或者如果类具有未定义它的成员   自己的复制操作,编译器无法合成移动   构造

有些代码似乎违反了这条规则:

#include <utility>
#include <iostream>

struct X {
    X() = default;
    X(const X&) { std::cout << "X(const X&)" << std::endl; }
    int i;
};

struct hasX {
    hasX() = default;
    hasX(const hasX &) = delete;
    hasX(hasX &&) = default;
    X mem;
};


int main()
{
    hasX hx, hx2 = std::move(hx);  //output is X(const X&)
}

X没有定义移动构造函数,编译器也无法合成它。

根据上述规则,hasX的移动构造函数将被删除。

但是,由于hasX的复制构造函数已被删除,hx2 = std::move(hx)必须调用移动构造函数来输出"X(const X&)",其中显示hasX&#39; s定义了移动构造函数,并使用X的复制构造函数来移动&#34;移动&#34;。这似乎违反了上述规则。

那么,是在C ++标准中定义还是仅仅是编译器实现?

我测试的编译器:VS2015和a online compiler

谢谢你的帮助!

1 个答案:

答案 0 :(得分:3)

你的书似乎错了。 Copying is a valid move operation因此,只要该成员具有const type&形式的复制构造函数,因此它可以绑定到rvalues,移动操作将回退到副本。

在你的例子中

hasX(hasX &&) = default;

可以替换为

hasX(hasX &&rhs) : mem(std::move(rhs.mem)) {}

因为这是默认的,它会编译得很好。