如果一个类没有默认构造函数,因为它应该始终初始化它的内部变量,那么它是否应该没有移动构造函数?
class Example final {
public:
explicit Example(const std::string& string) : string_(
string.empty() ? throw std::invalid_argument("string is empty") : string) {}
Example(const Example& other) : string_(other.string_) {}
private:
Example() = delete;
Example(Example&& other) = delete;
Example& operator=(const Example& rhs) = delete;
Example& operator=(Example&& rhs) = delete;
const std::string string_;
};
此类始终要求内部字符串由非空字符串设置,内部字符串在Example
个对象之间复制。我是否认为移动构造函数不适用于此处,因为如果移动了一个示例,则必须通过std::move
调用将该字符串留空?
答案 0 :(得分:6)
如果一个类没有默认构造函数,因为它应该始终初始化它的内部变量,那么它是否应该没有移动构造函数?
不,我不会这么说。
从Example
对象移动并留下空字符串的事实在这里应该不是问题,因为通常客户端不应该对移动对象的状态做出任何假设,除了这是合法的事实。
这意味着客户端只能调用对Example
输入状态没有先决条件的函数。请注意,通常几乎所有的Example
成员函数都会对对象的状态有先决条件(即string_
必须是非空字符串),但不是完全是所有的。
例如,Example
的析构函数不应该介意string_
是否为空 - 为什么即使在这种情况下它也不会被允许完成它的工作呢?赋值运算符是另一个常见示例 - 为什么不允许将新字符串分配给string_
?
在这个视图下,保留一个带有空字符串的Example
对象是可以的,因为所有客户端可以对移动的对象执行操作基本上是重新分配它或者销毁它 - 对于这些用例,string_
是否为空无关紧要。
因此,拥有移动构造函数和移动赋值运算符确实有意义。