不可抛出的不可移动类的对象
Objects of non-movable classes not throwable?
当使用 Clang 3.9.1 或 GCC 6.3.0 编译时,抛出可移动但不可复制的对象似乎工作正常:
struct MovableNonCopyable {
MovableNonCopyable();
~MovableNonCopyable();
MovableNonCopyable(MovableNonCopyable &&);
MovableNonCopyable(MovableNonCopyable const &) = delete;
MovableNonCopyable & operator=(MovableNonCopyable &&);
MovableNonCopyable & operator=(MovableNonCopyable const &) = delete;
};
void f() { throw MovableNonCopyable(); }
但是像这样扔可复制但不可移动的对象:
struct CopyableNonMovable {
CopyableNonMovable();
~CopyableNonMovable();
CopyableNonMovable(CopyableNonMovable &&) = delete;
CopyableNonMovable(CopyableNonMovable const &);
CopyableNonMovable & operator=(CopyableNonMovable &&) = delete;
CopyableNonMovable & operator=(CopyableNonMovable const &);
};
void g() { throw CopyableNonMovable(); }
而是会导致编译错误,例如:
test.cpp: In function 'void g()':
test.cpp:21:41: error: use of deleted function 'CopyableNonMovable::CopyableNonMovable(CopyableNonMovable&&)'
void g() { throw CopyableNonMovable(); }
^
test.cpp:15:9: note: declared here
CopyableNonMovable(CopyableNonMovable &&) = delete;
^~~~~~~~~~~~~~~~~~
这是为什么呢?根据 [except.throw#5],这应该是相反的方式,即复制构造函数应该是可访问的。
在这里,您显式要求编译器阻止来自右值对象的构造。
当您抛出临时CopyableNonMovable()
对象时,编译器会为其必须抛出的"副本"查找适当的构造函数。最适合的声明构造函数是移动构造函数,因为右值与右值引用绑定得最好。它查看声明,将其视为已删除,因此必须拒绝它。
最好的解决方案是简单地不声明移动构造函数,这将使它隐式不生成,因为声明了复制构造函数。在这种情况下,右值将最好地绑定到对const CopyableNonMoveable
相关文章:
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- 为什么协程的返回类型必须是可移动构造的?
- 我应该使我的局部变量常量还是可移动的
- 对于参加可复制和可移动类的访问者来说,应该有多少过载?
- 如何获取类型是否真正可移动可构造
- 可移动但不可复制的对象:按值传递还是按引用传递?
- 对于可移动类型,按值传递比重载函数更好吗?
- 使用参数将仅可移动对象捕获到 lambda
- 从从可调用参数创建的线程对象参数移动构造 C++11 线程
- C++11/VS2010:返回包含不可复制但可移动对象的容器
- 传递可移动对象
- 无法将可移动对象与Boost.Asio一起使用
- 如何按值返回一个不可复制的、可移动的对象作为const并存储它
- 在std::函数中存储不可复制但可移动的对象
- 在std::pair中存储不可复制(但可移动)的对象
- Boost序列化不可复制但可移动的对象
- 包含boost::可选对象的std::矢量对象是否可以移动?可移动助推::可选
- 编译器是否在最后一次使用可移动对象时自动使用移动语义?
- 外部模板类std::可移动对象的容器
- 作用于可移动但不可复制对象序列的变化STL算法的行为