什么是用例(如果有的话)使一个类不可移动?

And*_*hko 5 c++ boost move

考虑一种使类不可复制的经典方法:

// similar to boost::noncopyable
class noncopyable
{
protected:
    constexpr noncopyable() = default;

    noncopyable(const noncopyable&) = delete;
    noncopyable& operator=(const noncopyable&) = delete;
};

class c: private noncopyable
{ /* ... */ };
Run Code Online (Sandbox Code Playgroud)

由于声明任何复制操作都会阻止自动生成移动操作,因此这会自动使所有派生类都不可移动(默认情况下)(因此noncopyable将使用全名noncopyable_and_nonmoveable).

现在让我们从标准库中寻找经典的不可复制类,例如unique_ptr.它是不可复制但可移动的,否则其效用将受到限制.我认为对于许多其他情况也是如此.

实际上,当一个班级不可移动时,我无法想出任何一个例子.我的论点是:即使一个班级没有被计划移动,也有可能通过一个可能造成伤害的错误来完成.

这实际上是两个相关的问题:

1)为什么boost::noncopyable不可移动呢?这会导致问题,请考虑:

struct c: private boost::noncopyable
{
    std::unique_ptr<Something> something;

    c(c&&) = default;
    c& operator=(c&&) = default;
};
Run Code Online (Sandbox Code Playgroud)

不起作用(wandbox) - 无法生成移动操作,因为它们不是为基类生成的.您需要手动实现它们 - >列出您的成员 - >维护 - >错误.只是默认移动操作noncopyable会解决问题.

2)什么是可移动性有害的用例,应该防止它?

seh*_*ehe 8

不可移动使您可以更好地控制对象标识.

如果对象是可移动的,则其地址可以更改:

moveonly a;
b = std::move(a);
Run Code Online (Sandbox Code Playgroud)

现在,任何人仍然有一个a指向陈旧对象或(完全不同的东西)的引用.

出现这种情况的其他情况是,当你有外部逻辑取决于对象标识("地址稳定性"),如果你愿意,例如使用pthread互斥体:移动std :: mutex的构造函数

附录 - 命名约定scoped_XXXX常用于暗示不可移动的类型(即保证不可变实例标识的类型).将此与例如unique_XXXX暗示可以移动的唯一实例进行对比.但请注意,标准库并未完全采用此命名约定:示例:std::lock_guard<>vs std::unique_lock<>.C++ 17 对此进行修改