1. 依赖隐式自动移动构造函数是否安全?
没有测试(隐式或显式),没有什么是安全的。
2. 如何检查它是否真的有效,而不是默认的复制构造函数?
测试。请参阅下面的示例测试。
3. 最后,也是最重要的,这是一个好主意吗?为什么?还是定义我自己的总是更好?
使您的特殊成员变得微不足道有明显的(并且不断增长的)优势。一个平凡的特殊成员是由编译器定义/提供的。您可以使用 . 声明一个普通成员= default。其实最后一句话有点夸张。如果你用 声明一个特殊成员= default,它肯定不会是微不足道的。这取决于你的成员和基地。但是如果你明确地定义了一个特殊的成员(如在 C++98/03 中),那么它肯定不会是微不足道的。如果您可以在user-provided和trivial之间进行选择,请选择trivial。
此外,您不需要测试您的类型X是否具有移动构造函数。您需要测试,如果您移动构建您的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生成零代码,并且消耗的编译时间可以忽略不计。