提问者:小点点

在C 11中抛出异常时是否使用移动语义学?


http://www.drdobbs.com/cpp/practical-c-error-handling-in-hybrid-env/197003350?pgno=4

在本文中,Herb Sutter解释了抛出异常需要异常的副本,因为它是作为临时创建的,因此使用d::auto_ptr来绕过副本开销。鉴于C 11中提供的移动语义学,这还有必要吗?


共3个答案

匿名用户

我刚刚检查过,标准允许

  • 省略将由抛出表达式的操作数指定的对象复制或移动到异常对象中的操作

由于允许这些遗漏,规范要求首先将复制或移动的源视为右值。所以这意味着如果可能的话,相应的对象将被移动。当然,复制和移动省略仍然是允许的首选。

我被告知,将catch子句参数的异常对象初始值设定项视为右值初始值设定项的考虑可能会从标准中删除(因为一般来说,在忽略复制/移动时,不可能检测到所有情况下程序的行为是否保持不变),所以我建议不要依赖这个(上面的第二个项目)。

您仍然可以依赖的是将局部变量移动到异常对象中,如throw x(上面的第一个项目符号)。

匿名用户

从异常对象移动现在不是强制性的。

这是C11的缺陷。见CWG1493。

匿名用户

  • 在抛出表达式时,始终需要创建异常对象的副本,因为原始对象在堆栈展开过程中超出范围
  • 在初始化过程中,我们可能期望复制省略(见此)–忽略复制或移动构造函数(直接构造到目标对象存储中的对象)
  • 但是,即使复制省略可能会也可能不会被应用,您也应该提供适当的复制构造函数和/或移动构造函数,这是C标准要求的(参见15.1)。请参阅下面的编译错误以供参考

但是现代C提供了更多的特性:“使用移动语义安全地移动

struct demo
{
    demo() = default;
    demo(const demo &) { cout << "Copying\n"; }
    // Exception safe move constructor
    demo(demo &&) noexcept { cout << "Moving\n"; }
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

From:7 C中异常处理的最佳实践

相关问题