【发布时间】:2016-02-04 15:17:50
【问题描述】:
在 C++11 中,可以显式默认一个特殊的成员函数,如果它的隐式生成被自动阻止。
但是,显式默认一个特殊成员函数只是撤销了手动声明其他一些特殊成员函数(复制操作、析构函数等)而导致的隐式删除,并不强制编译器生成函数和代码即使函数实际上无法生成,也被认为是格式良好的。
考虑以下场景:
struct A
{
A () = default;
A (const A&) = default;
A (A&&) = delete; // Move constructor is deleted here
};
struct B
{
B () = default;
B (const B&) = default;
B (B&&) = default; // Move constructor is defaulted here
A a;
};
编译器不会生成B中的move构造函数,因为这样做会导致编译错误(A的move构造函数被删除)。如果不显式删除 A 的构造函数,B 的移动构造函数将按预期生成(复制 A,而不是移动它)。
尝试移动这样的对象将默默地使用复制构造函数:
B b;
B b2 (std::move(b)); // Will call B's copy constructor
有没有办法强制编译器生成函数或在不能生成函数时发出编译错误?如果没有这个保证,如果单个删除的构造函数可以禁用整个对象层次结构的移动,则很难依赖默认的移动构造函数。
【问题讨论】:
-
你不知道你加入的成员是否可以移动吗?
-
它们在最初实现类时可能是可移动的,但是,如果以后添加更多成员,则可能会忽略可移动要求(尤其是如果它们是由其他人添加的)。
-
应该注意,删除其移动构造函数但不其复制构造函数的类型非常...奇怪。这样做绝对没有任何收获。所以最好忽略这种情况,认为它是某人无缘无故做一些愚蠢的事情的结果。
-
@JanHolecek:有关这方面的更多详细信息,请参阅this question。
-
定义类外的函数为默认值。