是否有可能具有放入容器的移动操作的类型?

Could it be possible to have types with move operations that throw in containers?

本文关键字:移动 操作 类型 有可能 是否      更新时间:2023-10-16

在与同事解释对象的移动操作时,我基本上说移动操作不应该在容器中抛出异常,因为如果移动操作失败,那么就没有办法可靠地恢复原始对象。 仔细考虑这一点,我想知道这是否不正确,如果确实抛出移动操作,它可以将原始对象恢复到其原始状态。

这样做的原因是,如果一个对象可以抛出,那么它不会抛出,不是因为将包含的对象从旧地址复制或移动到新地址,而是在资源获取失败时抛出。 所以所有的原始信息应该仍然存在。 如果是这种情况,那么编译器是否应该不能撤消它为重建原始对象所做的操作?

操作可能是单向的,例如移动整数,但在这种情况下,它可能只是终止应用程序,如果开发人员想要避免单向操作,也许可以使用交换方法代替。

这只能在默认移动运算符上实现,因为如果存在任何其他逻辑,编译器可能很难执行反向部分转换。

我是不是把事情简单化了? 我错过了什么东西,可以在没有非抛出移动构造函数/运算符的情况下阻止容器移动对象?

您可以在容器(如vector(中使用具有抛出移动的类型,这些容器可以移动其元素。但是,此类容器不会使用抛出移动操作。

假设您有 10 个投掷动作元素的vectorvector需要调整自身大小。因此,它将 5 个对象移动到新内存中,但第 6 个对象会抛出。嗯,没关系;构造失败,因此假设第 6 个对象的值很好。也就是说,无论该类型的异常保证是什么,都将是事情的工作方式。

但是,由于一个对象的移动失败,vector需要将最后 5 个对象移第一个数组,因为vector试图提供强大的异常保证。这是一个问题,因为后移本身可能会失败

当修复故障的过程本身失败时,C++通常没有有效的答案。您可以在例外中看到这一点;不能从由于异常失败而在展开过程中调用的析构函数发出异常。 在这种情况下std::terminate发生。

vector也是如此.如果回退失败,vector没有理智的答案。因此,如果vector不能保证恢复其以前的数组状态是noexcept,那么它将使用复制,因为这可以提供这种保证。

首先,我很难想象在移动操作中获取资源的对象。想想看 -unique_ptr只是传递指针而没有获得任何东西,shared_ptr也是如此.stringvector,所有包含器等只是窃取指向默认或复制构造函数中先前获取的资源的指针。我觉得从移动构造函数中抛出就像从析构函数中抛出一样。当然,继续,向自己的膝盖开枪。但是好吧,我可以接受存在例外情况。

因此,让我们转到第二点 - 移动时,实际上两个对象(从和移动到(都无效。要从这种情况回滚,需要调用额外的"魔术"函数来修复其中一个。因此,数据似乎无法修复,因为标准没有定义这样的功能。