是否有可能具有放入容器的移动操作的类型?
Could it be possible to have types with move operations that throw in containers?
在与同事解释对象的移动操作时,我基本上说移动操作不应该在容器中抛出异常,因为如果移动操作失败,那么就没有办法可靠地恢复原始对象。 仔细考虑这一点,我想知道这是否不正确,如果确实抛出移动操作,它可以将原始对象恢复到其原始状态。
这样做的原因是,如果一个对象可以抛出,那么它不会抛出,不是因为将包含的对象从旧地址复制或移动到新地址,而是在资源获取失败时抛出。 所以所有的原始信息应该仍然存在。 如果是这种情况,那么编译器是否应该不能撤消它为重建原始对象所做的操作?
操作可能是单向的,例如移动整数,但在这种情况下,它可能只是终止应用程序,如果开发人员想要避免单向操作,也许可以使用交换方法代替。
这只能在默认移动运算符上实现,因为如果存在任何其他逻辑,编译器可能很难执行反向部分转换。
我是不是把事情简单化了? 我错过了什么东西,可以在没有非抛出移动构造函数/运算符的情况下阻止容器移动对象?
您可以在容器(如vector
(中使用具有抛出移动的类型,这些容器可以移动其元素。但是,此类容器不会使用抛出移动操作。
假设您有 10 个投掷动作元素的vector
。vector
需要调整自身大小。因此,它将 5 个对象移动到新内存中,但第 6 个对象会抛出。嗯,没关系;构造失败,因此假设第 6 个对象的值很好。也就是说,无论该类型的异常保证是什么,都将是事情的工作方式。
但是,由于一个对象的移动失败,vector
需要将最后 5 个对象移回第一个数组,因为vector
试图提供强大的异常保证。这是一个问题,因为后移本身可能会失败。
当修复故障的过程本身失败时,C++通常没有有效的答案。您可以在例外中看到这一点;不能从由于异常失败而在展开过程中调用的析构函数发出异常。 在这种情况下std::terminate
发生。
vector
也是如此.如果回退失败,vector
没有理智的答案。因此,如果vector
不能保证恢复其以前的数组状态是noexcept
,那么它将使用复制,因为这可以提供这种保证。
首先,我很难想象在移动操作中获取资源的对象。想想看 -unique_ptr
只是传递指针而没有获得任何东西,shared_ptr
也是如此.string
,vector
,所有包含器等只是窃取指向默认或复制构造函数中先前获取的资源的指针。我觉得从移动构造函数中抛出就像从析构函数中抛出一样。当然,继续,向自己的膝盖开枪。但是好吧,我可以接受存在例外情况。
因此,让我们转到第二点 - 移动时,实际上两个对象(从和移动到(都无效。要从这种情况回滚,需要调用额外的"魔术"函数来修复其中一个。因此,数据似乎无法修复,因为标准没有定义这样的功能。
- 复制和交换习惯用法与移动操作之间的交互
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 这将执行默认移动操作吗?
- 如何对移动操作进行单元测试(默认)?
- 我是否缺少<实验/文件系统>移动操作?
- 是否有可能具有放入容器的移动操作的类型?
- 我什么时候需要移动操作,c++
- 变量可以通过C / C 的左或右移动操作变为null
- 标准::atomic_应该如何...<std::shared_ptr>用于线程安全类的复制和移动操作?
- 为什么C++允许您移动包含已删除移动操作的对象的类
- "pair::operator=(pair&&)"错误,"auto&"推断出移动操作 - libstdc++ 回归?
- 具有可以引发的移动操作的仅移动类的示例是什么?
- C++11:执行移动操作以更改地址
- 不理解 Stroustup 先生的建议,删除复制默认值并为抽象类 Shape 移动操作
- 默认的虚拟析构函数是否阻止编译器生成的移动操作
- 为什么在声明移动操作时删除复制操作?
- 具有移动操作和重新值转发的对象生存期
- "Inherit"移动操作,而无需访问基类成员变量
- 隐式声明的移动操作不会回退到复制
- 简单的复制和移动操作有什么不同吗?