在C++11中抛出异常时,是否使用移动语义
Does an exception use move semantics when thrown in C++11?
http://www.drdobbs.com/cpp/practical-c-error-handling-in-hybrid-env/197003350?pgno=4
在本文中,Herb Sutter解释了抛出异常需要一个异常的副本,因为它是作为临时创建的,因此使用std::auto_ptr
来绕过复制开销。鉴于移动语义在C++11中可用,这仍然是必要的吗?
我刚刚检查过,标准允许
- 省略将throw表达式的操作数指定的对象复制或移动到异常对象中
- 如果您不以其他方式更改程序的含义(即,如果您将重新抛出,并且随后的catch会突然看到一个更改的异常对象被前一个catch块更改),则省略将异常对象复制或移动到与异常对象相同类型的catch子句变量中
由于允许这些遗漏,规范要求首先将复制或移动的源视为右值。因此,这意味着如果可能的话,相应的对象将被移动。当然,复制和移动省略仍然是第一选择。
更新
我被告知,catch子句参数的异常对象初始值设定项作为右值初始值设定值的考虑可能会从标准中删除(因为通常情况下,在省略复制/移动时,不可能在所有情况下都检测到程序的行为何时保持不变),所以我建议不要依赖这一点(上面的第二个项目符号)。
仍然可以依赖的是将局部变量移动到异常对象中,如throw x;
(上面的第一个项目符号)所示。
从异常对象中移动现在不是强制性的。
这是C++11的一个缺陷。参见CWG1493。
- 在抛出表达式时,当原始对象在堆栈展开过程中超出范围时,总是需要创建异常对象的副本
- 在初始化过程中,我们可能会期望复制省略(请参阅此)-省略复制或移动构造函数(直接构建到目标对象存储中的对象)
- 但是,即使可能应用或不应用复制省略,您也应该提供适当的复制构造函数和/或移动构造函数,这是C++标准要求的(请参见15.1)。请参阅以下编译错误以供参考
但现代C++提供了更多功能:"使用移动语义和异常安全移动"
struct demo
{
demo() = default;
demo(const demo &) { cout << "Copyingn"; }
// Exception safe move constructor
demo(demo &&) noexcept { cout << "Movingn"; }
private:
std::vector<int> m_v;
};
int main()
{
demo obj1;
if (noexcept(demo(std::declval<demo>()))){ // if moving safe
demo obj2(std::move(obj1)); // then move it
}
else{
demo obj2(obj1); // otherwise copy it
}
demo obj3(std::move_if_noexcept(obj1)); // Alternatively you can do this----------------
return 0;
}
- 我们可以使用
noexcept(T(std::declval<T>()))
来检查T
的移动构造函数是否存在并且是noexcept
,以便决定是否要通过移动T
的另一个实例来创建T
的实例(使用std::move
) - 或者,我们可以使用
std::move_if_noexcept
,它使用noexcept
运算符并强制转换为右值或左值。这种检查用于std::vector
和其他容器 - 当您处理不想丢失的关键数据时,这将非常有用。例如,我们有从服务器接收的关键数据,我们不想在处理过程中不惜任何代价丢失这些数据。在这种情况下,我们应该使用
std::move_if_noexcept
,它将仅在移动构造函数是异常安全的情况下移动关键数据的所有权
来自:C++中异常处理的7个最佳实践
相关文章:
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 可以使用移动语义更改或改进此C++代码吗?
- c++在使用指针时移动语义
- 移动语义和深层/浅层复制之间有什么关系?
- std::unique_lock移动语义
- 移动语义和运算符 + 重载
- C++ 移动语义是否在任何情况下都能节省资源?
- 移动语义在这里如何工作?
- 使用移动语义:右值引用作为方法参数
- 在C++中使用移动语义的正确方法是什么?
- 移动语义 c++ 单链表
- C++:使用整数移动语义
- 当变量和参数名称匹配时,移动语义构造失败
- 在 C++11 中移动语义
- 方法冗余移动调用的移动语义
- 复制省略并在返回值中移动语义
- std::元组和移动语义
- 移动语义与返回shared_ptr?
- C++具有移动语义的可变参数工厂会导致运行时崩溃