c++ 允许分配器构造和销毁成员函数从内部逻辑抛出异常吗?

au9on6nz  于 2023-05-24  发布在  其他
关注(0)|答案(2)|浏览(249)

我正在编写自己的容器,它不需要任何可移动和可复制类型。我想我可以在异常安全性方面简化一下逻辑。但是我注意到分配器的constructdestroy成员函数没有关于何时可以和何时不能抛出异常的措辞。
我很确定我以前读过这个词。否则,即使我的类型是nothrow可移动的,construct仍然可以从用户提供的分配器中抛出异常,比如说,当我调整缓冲区大小以增加容量时。这需要复杂的回滚代码来保证强大的异常安全性,我真的想跳过。
是否有一种措辞只允许从调用ctor/dtor抛出异常,或者分配器总是需要复杂的机制来维护异常安全?

qoefvg9y

qoefvg9y1#

分配器成员可以抛出。如果标准没有说他们不能扔,那么他们可以扔。
但实际上,他们为什么要这样做呢?
特别是对于std::allocator::constructstd::allocator::destroy,它们除了调用构造函数或析构函数之外什么也不做。但是无论如何,您都应该使用std::allocator_traits<Alloc>::constructstd::allocator_traits<Alloc>::destroy,如果存在Alloc::construct/Alloc::destroy,它们只会调用Alloc::construct/Alloc::destroy,否则调用构造函数/析构函数。
理论上,病态分配器可以放入这些成员,但您应该假设它们不会。你不能防御病态愚蠢的类型。

u4vypkhs

u4vypkhs2#

他们的疏忽有一个(或两个)原因。首先,析构函数可以抛出。其次,标准希望避免在有用的上下文中出现未定义的行为。如果他们完全禁止在分配器中抛出destroy,那么您就不可能在destroy函数中拥有一个执行重要工作的分配器。想象一下,在测试中,你可以使用一个分配器来跟踪对象的分配、释放、构造和销毁。在这种情况下,destroy可能会抛出,因为分配器可能正在引用一些需要存储数据的容器。然而,一个优秀的开发人员应该知道,抛出一个析构函数,或者,在本例中,分配器的destroy方法,可能会使整个程序的状态无效。因此,在几乎所有情况下,您都可以使用destroy,因为 * 如果 * 它不会抛出,并且允许未处理的异常/终止。

相关问题