5

如果一个类没有默认构造函数,因为它应该始终初始化它的内部变量,那么它不应该有移动构造函数吗?

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调用将字符串留空?

4

1 回答 1

6

如果一个类没有默认构造函数,因为它应该始终初始化它的内部变量,那么它不应该有移动构造函数吗?

不,我不会这么说

从一个Example对象移动并留下一个空字符串的事实在这里应该不是问题,因为通常客户端不应该对移动对象的状态做出任何假设,除了它是合法的事实。

这意味着,客户端只能调用对其Example输入状态没有先决条件的函数。请注意,通常的几乎所有成员函数Example都会对对象的状态有先决条件(即string_必须是非空字符串),但并非全部都是。

例如,Example不应该介意的析构函数是否string_为空 - 为什么即使在这种情况下也不允许它完成它的工作?赋值运算符是另一个常见的例子——为什么不允许给string_? 赋值一个新的字符串。

在这种观点下,留下一个Example空字符串的对象是可以的,因为客户可以对一个移动的对象做的所有事情基本上要么重新分配它,要么销毁它——对于这些用例,是否string_为空并不重要.

因此,拥有一个移动构造函数和一个移动赋值运算符确实是有意义的

于 2013-04-15T16:05:59.293 回答