依赖隐式声明的move构造函数安全吗
Is it safe to rely on an implicitly declared move constructor?
这是我获得大部分信息的地方:http://en.cppreference.com/w/cpp/language/move_constructor
显然,这些是隐式生成的移动构造函数工作的条件:
- 没有用户声明的副本构造函数
- 没有用户声明的副本分配运算符
- 没有用户声明的移动分配运算符
- 没有用户声明的析构函数
- 隐式声明的move构造函数未定义为已删除
- 如果存在用户声明的移动构造函数,则仍然可以强制生成具有关键字
default
的隐式声明的移动构造器
我的问题是:
- 依赖隐式自动移动构造函数安全吗
- 如何检查它是否真的有效,而不是默认的复制构造函数
- 最后,也是最重要的一点,这是一个好主意吗?为什么?还是总是更好地定义我自己的
我更倾向于遵循三规则,手动创建析构函数、复制和移动构造函数以及复制和移动赋值运算符,但我只是对这个隐式感到好奇。
以下是您问题的答案:
- 你说"安全"是什么意思?当规则适用时,即子对象是可移动的,并且您没有做任何事情来阻止移动构造函数的生成,它将在存在时创建和使用。然而,请注意,有一个不可移动的子对象很容易,这会在某种程度上无形地抑制移动构造函数的创建
- 要查看您的类是否获得了move构造函数,只需在使用copy和move构造函数时临时添加一个空的基日志记录,并强制移动/复制对象:它将记录相应使用的构造函数
- 一般来说,没有代码比任何代码都好
CCD_ 2。依赖隐式自动移动构造函数安全吗?
未经测试(隐式或显式),没有什么是安全的。
2
。如何检查它是否真的有效,而不是默认的复制构造函数?
测试。请参阅下面的示例测试。
3
。最后,也是最重要的一点,这是一个好主意吗?为什么?还是总是更好地定义我自己?
让您的特殊成员变得微不足道有着明显的(且不断增长的)优势。琐碎的特殊成员是由编译器定义/提供的。您可以用= default
声明一个琐碎的成员。事实上,最后一句话是夸大其词。如果您用= default
声明一个特殊成员,那么它肯定不是微不足道的。这取决于你的成员和基础。但是,如果您显式地定义了一个特殊的成员(如在C++98/03中),那么它肯定不会是微不足道的。如果您可以在用户提供的和琐碎之间进行选择,请选择平凡。
此外,您不需要测试类型X
是否具有move构造函数。您需要测试,如果移动构造您的X
,它是否具有正确的异常安全性和正确的性能。如果X::X(const X&)
完成了这个任务,那就顺其自然吧。在这种情况下,X::X(X&&)
就没有必要了。
如果你期望你的类型X
将有一个抛出复制构造函数,以及一个更快的noexcept
移动构造函数,这里有一个非常好的测试来确认它是这样的:
static_assert(std::is_nothrow_move_constructible<X>::value,
"X should move construct without an exception");
把这个测试放在你的源/头中。现在,无论您是隐式地,还是显式地声明或定义您的特殊成员,您都得到了一个实际为零成本的具体编译时测试。static_assert
生成的代码为零,并且消耗的编译时间可以忽略不计。
- 使用范围解析运算符时,在构造函数中调用虚拟方法是否安全?
- 构造函数成员初始值设定项跨成员列出,安全吗?
- 为什么在构造函数中将字符串分配给指针是安全的?
- 将数据成员的指针传递给基类构造函数是否安全?
- 是STD :: REGEX构造函数安全
- C++中构造函数和布尔的安全空状态:
- 在可移动类型的构造函数 lambda 中捕获此内容的安全使用
- 在已发布的结构中添加构造函数(用于 memcpy)是否安全?
- 以下移动构造函数代码安全吗?
- 与构造函数参数相关的异常安全的习语
- 在构造函数中使用"this"启动线程是安全的?
- 异常安全构造函数
- 将子结构值设置为对象构造函数中安全的纯虚拟函数返回的值
- 指向调用类的构造函数的资源是否安全?
- 这段代码安全吗,是否可以从构造函数C++生成线程
- 根据C++标准,显式调用构造函数和析构函数是否安全
- 在构造函数中记录此值是否安全
- 构造函数在 C++ 和/或 C++11 中是否安全
- 锁定线程安全队列的移动构造函数的右值参数?
- 依赖隐式声明的move构造函数安全吗