考虑一种使类不可复制的经典方法:
// 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)什么是可移动性有害的用例,应该防止它?
不可移动使您可以更好地控制对象标识.
如果对象是可移动的,则其地址可以更改:
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 对此进行了修改
| 归档时间: |
|
| 查看次数: |
215 次 |
| 最近记录: |