http://www.drdobbs.com/cpp/practical-c-error-handling-in-hybrid-env/197003350?pgno=4
在这篇文章中,Herb Sutter 解释了抛出异常需要一个异常的副本,因为它是作为临时创建的,因此使用 anstd::auto_ptr
来绕过复制开销。鉴于 C++11 中提供了移动语义,这还有必要吗?
http://www.drdobbs.com/cpp/practical-c-error-handling-in-hybrid-env/197003350?pgno=4
在这篇文章中,Herb Sutter 解释了抛出异常需要一个异常的副本,因为它是作为临时创建的,因此使用 anstd::auto_ptr
来绕过复制开销。鉴于 C++11 中提供了移动语义,这还有必要吗?
我刚刚检查过,标准允许
由于允许这些省略,规范要求首先将复制或移动的来源视为右值。所以这意味着如果可能的话,相应的对象将被移动。当然,复制和移动省略仍然可以作为首选。
我被告知,将 catch 子句参数的异常对象初始化程序作为右值初始化程序的考虑可能会从标准中删除(因为通常不可能在所有情况下检测到省略时程序的行为何时保持不变复制/移动),所以我建议不要依赖这个(上面的第二个项目符号)。
您仍然可以依赖的是将局部变量移动到异常对象中,如throw x;
(上面的第一个项目符号)。
从异常对象移动现在不是强制性的。
这是C++11的一个缺陷。参见CWG1493。
但现代 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<T>()))
来检查是否T
存在移动构造函数,并且是noexcept
为了决定是否要T
通过移动T
(使用std::move
)的另一个实例来创建一个实例。std::move_if_noexcept
,它使用noexcept
运算符并强制转换为右值或左值。此类支票用于std::vector
其他容器。std::move_if_noexcept
which 将仅移动关键数据的所有权并且仅当移动构造函数是异常安全的。