C++移动语义和异常

26 c++ exception move-semantics c++11

在即将推出的C++ 0x标准中,当在移动构造函数中/期间抛出异常时会发生什么?

原始物体会保留吗?或者是处于未定义状态的原始对象和移动对象?语言提供的保证是什么?

Mic*_*urr 11

我相信标准委员会最初试图让它变得如此移动构造函数不会被允许抛出异常,但(至少截至今天)发现试图强制执行有太多陷阱.

提案N3050,"允许移动构造者投掷(第1版)"已被纳入标准草案.本质上,该提议增加了移动构造函数抛出的能力,但禁止"抛出"移动用于需要强大的异常安全保证的某些操作(如果非抛掷移动不是,则库将回退到复制对象)可用).

如果将move构造函数标记为非throw(noexcept)并抛出异常,则将调用std :: terminate().

也许值得阅读David Abrahams撰写的博客文章,该文章讨论了N3050旨在解决的问题:

  • 是的,我也发现整个cpp-next博客网站非常有趣的文章! (3认同)

Fre*_*urk 3

取决于要移动的类型。当然,可以从移动构造函数显式抛出异常,也可以从移动构造函数隐式调用子对象的复制构造函数。该复制构造函数可能会执行一些可能引发异常的操作,例如分配内存。因此,对于源对象,最低限度的保证是原始值可能保留也可能不保留,但它仍然应该处于可破坏的状态。

\n\n

对于要移动到的对象,它与当前 C++ 中的 ctor 抛出相同:销毁所有构造的基类和成员,执行 ctor 的函数 try 处理程序(如果有),然后传播异常。详细信息位于 N3225 \xc2\xa715.2p2 中。

\n\n

特别要注意的是,容器要求其分配器类型不具有抛出移动向量:

\n\n
\n

分配器的此类移动构造不应通过异常退出。[N3225\xc2\xa723.2p8]

\n
\n\n

这允许容器四处移动分配器,并在移动或复制项目时出现异常时使用这些分配器来清理其项目。

\n