移动构造函数和强异常保证

17

有一个快速的问题,我找不到好的参考资料,尤其是关于未来的C++0x标准的当前实现。

由于移动构造函数可能会抛出异常,这意味着一些标准库函数无法提供强异常保证(例如vector<T>::resize())。

曾经有一个提案,即1)使所有标准库移动构造函数“不可抛”,以及2)在用户代码中添加编译时检查,以确保例如std::pair<std::string, MyType>定义了一个不可抛的移动构造函数或根本没有移动构造函数。

这个提案最终怎么样了(特别是关于这个问题的回答)?该问题在最终草案中如何“解决”?

最重要的是,当我使用最近的GCC或MSVC 10时,对我有什么影响?那些标准库的实现是否对例如std::vector<MyTypeWithAThrowingMoveConstructor>::resize()提供了强异常保证?

编辑:我没有看到这个问题,它显然是相关的。如果有关于我的问题是重复的共识,请关闭它。但是,我真的很想知道已经实现的,而不是正在讨论的


+1个相当好奇的问题 - sehe
他们是否提供了强异常保证?我的意思是,你的复制构造函数总是可能会抛出异常,所以... - Xeo
@Xeo: 是的,他们做到了。回滚一个大小调整操作很容易,因为旧缓冲区在所有副本都成功之后被销毁。如果有一个不抛异常的移动构造函数,你也可以通过将元素移回旧缓冲区来回滚。但是,如果使用会抛出异常的移动构造函数,可能会发生一些不好的事情。在这里我们可以清楚地看到缺少一个强大的 noexcept 关键字。 - Alexandre C.
@Xeo:在复制操作中提供强异常保证很容易。如果有任何一份副本失败,那么你可以恢复到原始状态(原始状态没有改变)。移动操作的问题在于你已经修改了原始状态。因此,在移动容器时,如果在第三个元素上抛出异常,就不能保证前两个元素能够恢复到它们的原始状态。 - Martin York
1个回答

5

我没有检查具体的实现,但是一般的想法是如果移动构造函数可以抛出异常,那么vector必须复制元素。这样在发生异常时可以回滚。

甚至还有一个辅助函数move_if_noexcept定义在<utility>中来帮助它决定该做什么。


有趣。我要检查一下我感兴趣的库中是否存在这个 move_if_noexcept(顺便说一下,你打错了)助手。 - Alexandre C.
3
@Alexander - MSVC10无法完全符合规范,因为其发布后rvalue规则已更改。 - Bo Persson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接