移动构造函数是隐式的吗? [英] Can a move constructor be implicit?
问题描述
考虑下面的类:
class A
{
public:
std :: string field_a;
std :: string field_b;
}
现在考虑以下副本构造:
A a1(a2);
复制结构将充分复制 A
缺少一个显式的拷贝构造函数,因为 std :: string
的拷贝构造函数将被编译器生成的隐式拷贝构造函数调用。
$
编辑:测试此处显示:
A a2(std :: move(a1));
实际上会导致复制构造,除非特定的move构造函数:
A(A&& other):a(std :: move(other.a)){}
已定义。
EDIT EDIT
我ping了Stephan T Lavavej,问他为什么VC 2012似乎不遵循12.8中关于隐式移动构造函数生成的草案。他很善良地解释:
这更像是一个功能尚未实现比一个错误。 VC目前
实现我所谓的右值引用v2.0,其中move
ctors / assigns绝不会隐式生成,永远不会影响
隐式生成复制ctors / assigns。 C ++ 11指定rvalue
引用v3.0,这是您正在查找的规则。
解决方案是的,从C ++ 11草案,12.8:
如果类X的定义没有明确声明一个移动构造函数,当且仅当
时,会隐式声明
为默认值X没有用户-declared copy constructor,
- X没有用户声明的复制赋值运算符,
- X没有用户声明的,
- X没有用户声明的析构函数,
- move构造函数不会被隐式定义为已删除。
后面的条件指定更多细节:
隐式声明的复制/移动构造函数是其类的内联公共成员。如果X具有:
- 一个类的X的默认复制/移动构造函数定义为已删除非平凡的相应构造函数,X是类似union的类,
- 类型为M(或其数组)的非静态数据成员不能被复制/移动,因为$ b $如果应用于M的相应构造函数,则b重载分辨率(13.3)导致从默认构造函数中删除或不可访问的模糊度或
函数。
- 直接或虚拟不能被复制/移动的基类B,因为重载分辨率(13.3)作为
应用于B的相应构造函数导致模糊性或被删除的函数或
不能从默认构造函数访问, li>
- 任何直接或虚拟基类或非静态数据成员,其类型的析构函数被删除
或从默认构造函数无法访问
- 为复制构造函数,右值引用类型的非静态数据成员,或
- 用于移动构造函数,非静态数据成员或直接或虚拟基类
很明显,移动构造函数将被隐式声明为:
- 该类没有用户声明的任何其他特殊成员函数。
- 移动构造函数可以通过移动其所有成员和基数来实现。
您的类显然符合这些条件。
Consider the following class:
class A { public: std::string field_a; std::string field_b; }
Now consider the following copy construction:
A a1(a2);
The copy construction will adequately copy
A
despite the lack of of an explicit copy constructor because the copy constructors forstd::string
will be called by the compiler generated implicit copy constructor.What I wish to know is, is the same true for move construction?
EDIT: Testing here shows that:
A a2(std::move(a1));
Will actually result in a copy construction, unless the specific move constructor:
A( A && other ) : a(std::move(other.a)) {}
Is defined.
EDIT EDIT I pinged Stephan T Lavavej and asked him why VC 2012 doesn't seem to follow what draft 12.8 states regarding implicit move constructor generation. He was kind enough to explain:
It's more of a "feature not yet implemented" than a bug. VC currently implements what I refer to as rvalue references v2.0, where move ctors/assigns are never implicitly generated and never affect the implicit generation of copy ctors/assigns. C++11 specifies rvalue references v3.0, which are the rules you're looking at.
解决方案Yes, from the C++11 draft, 12.8:
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
- X does not have a user-declared copy constructor,
- X does not have a user-declared copy assignment operator,
- X does not have a user-declared move assignment operator,
- X does not have a user-declared destructor, and
- the move constructor would not be implicitly defined as deleted.
The latter condition is specified with more detail later:
An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:
- a variant member with a non-trivial corresponding constructor and X is a union-like class,
- a non-static data member of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
- a direct or virtual base class B that cannot be copied/moved because overload resolution (13.3), as applied to B’s corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
- any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,
- for the copy constructor, a non-static data member of rvalue reference type, or
- for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.
Plainly speaking, the move constructor will be implicitly declared if:
- The class does not have user-declared any of the other special member functions.
- The move constructor can be sensibly implemented by moving all its members and bases.
Your class obviously complies with these conditions.
这篇关于移动构造函数是隐式的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!