c-引发异常时不调用Move构造函数
作者:互联网
我有一个变量,它会累积当前异常,并且在抛出当前异常时需要清除该变量(这样就不会再次报告相同的错误).问题是抛出std :: move(ex);不调用move构造函数(这将清除ex),而是调用一个复制构造函数(这样ex也会保留已引发的错误). MVCE遵循:
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;
class ThrowMoveTest : exception
{
public:
ThrowMoveTest(const string& what)
{
_what = what;
}
ThrowMoveTest(const ThrowMoveTest& fellow)
{
cout << "Copy " << what() << endl;
_what = fellow._what;
}
ThrowMoveTest(ThrowMoveTest&& fellow)
{
cout << "Move " << what() << endl;
_what = std::move(fellow._what);
}
virtual const char* what() const override
{
return _what.c_str();
}
private:
mutable string _what;
};
int main()
{
try
{
ThrowMoveTest tmt1("Test1");
throw move(tmt1);
}
catch (const ThrowMoveTest& ex)
{
cout << "Caught " << ex.what() << endl;
}
return 0;
}
我正在使用MSVC 2013 Update 5.
我在做错什么事,因此不因此而调用move构造函数吗?是否有引发异常的方法,以便在C中用于异常存储的临时对象是移动构造的,而不是从原始副本构造的?
我要避免的是双重复制:构造tmt1的副本,然后清洗原始副本,然后使用copy in throw语句,这将构造另一个副本用于临时存储.
编辑:上面的代码示例在MSVC 2013 Update 5上提供以下输出
Copy
Caught Test1
虽然预期的输出是
Move
Caught Test1
EDIT2:提交了一个编译器错误报告https://connect.microsoft.com/VisualStudio/feedback/details/1829824
解决方法:
这是一个MSVC错误.从[除外]:
Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object.
这意味着我们这样做:
ThrowMoveTest __exception_object = move(tmt1);
绝对应该调用move构造函数.
请注意,此处的移动是不必要的,也会造成破坏. [class.copy]规定可以删除复制/移动构造
— in a throw-expression (5.17), when the operand is the name of a non-volatile automatic object (other than
a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost
enclosing try-block (if there is one), the copy/move operation from the operand to the exception
object (15.1) can be omitted by constructing the automatic object directly into the exception object
因此,只需抛出tmt1;本来可以将tmt1直接构建到异常对象中.尽管gcc和clang都不这样做.
即使不忽略复制/移动,也可以:
When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the
object to be copied is designated by an lvalue […] overload resolution
to select the constructor for the copy is first performed as if the object were designated by an rvalue.
因此抛出tmt1;仍将移动构造异常对象.
标签:move-constructor,c,c11,exception,move-semantics 来源: https://codeday.me/bug/20191011/1895540.html