考虑以下课程:
class A
{
public:
std::string field_a;
std::string field_b;
}
现在考虑以下复制结构:
A a1(a2);
复制结构将充分复制 A
尽管缺少显式的复制构造函数,因为复制构造函数为 std::string
将由编译器生成的隐式复制构造函数调用。
我想知道的是,移动建筑也是如此吗?
编辑:测试 这里 表明:
A a2(std::move(a1));
实际上会导致复制构造,除非特定的移动构造函数:
A( A && other ) : a(std::move(other.a)) {}
被定义为。
编辑编辑
我谴责了Stephan T Lavavej,并问他为什么VC 2012似乎没有遵循12.8关于隐式移动构造函数生成的草案。他很友善地解释道:
它更像是一个“尚未实现的功能”,而不是一个bug。 VC目前
实现我所称的右值引用v2.0,其中move
ctors / assign永远不会隐式生成,永远不会影响
隐式生成复制ctors / assign。 C ++ 11指定rvalue
引用v3.0,这是你正在看的规则。
是的,来自C ++ 11草案,12.8:
如果类X的定义没有显式声明移动构造函数,则将隐式声明一个
当且仅当如此,违约
- X没有用户声明的复制构造函数,
- X没有用户声明的复制赋值运算符,
- X没有用户声明的移动赋值运算符,
- X没有用户声明的析构函数,和
- 移动构造函数不会被隐式定义为已删除。
后面的条件稍后详细说明:
隐式声明的复制/移动构造函数是其类的内联公共成员。如果X具有以下内容,则将类X的默认复制/移动构造函数定义为已删除(8.4.3):
- 具有非平凡对应构造函数的变体成员,X是类似联合的类,
- 类类型M(或其数组)的非静态数据成员,由于无法复制/移动
重载决策(13.3),应用于M的相应构造函数,导致模糊或a
从默认构造函数中删除或无法访问的函数,
- 由于重载决策(13.3)而无法复制/移动的直接或虚拟基类B.
应用于B的相应构造函数,导致歧义或被删除的函数或
默认构造函数无法访问,
- 具有被删除的析构函数的类型的任何直接或虚拟基类或非静态数据成员
或默认构造函数无法访问,
- 对于复制构造函数,rvalue引用类型的非静态数据成员,或
- 对于移动构造函数,一个非静态数据成员或直接或虚拟基类,其类型不具有移动构造函数,并且不易于复制。
简而言之,如果符合以下情况,将隐式声明移动构造函数:
- 该类没有用户声明的任何其他特殊成员函数。
- 移动构造函数可以通过移动其所有成员和基础来合理地实现。
你的班级显然符合这些条件。
如果可以,并且如果没有用户定义的复制构造函数,编译器将合成移动构造函数。如果存在复制构造函数则没有合成移动构造函数的限制旨在避免破坏现有代码。当然,所有成员都需要移动。确切的规则涉及更多。