当使用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],这应该是另一种方式,即复制构造函数应该是可访问的.
最佳答案 在这里,您明确要求编译器阻止构造rvalue对象.
抛出临时的CopyableNonMovable()对象时,编译器会为其必须抛出的“副本”查找相应的构造函数.最适合的声明构造函数是移动构造函数,因为rvalues最适合rvalue引用.它查看声明,将其视为已删除,因此必须拒绝它.
最好的解决方案是简单地不声明移动构造函数,因为声明了复制构造函数,这将使其隐式生成.在这种情况下,rvalues将最好地绑定到const CopyableNonMoveable的引用