我正在编写自己的容器,它不需要任何可移动和可复制类型。我想我可以在异常安全性方面简化一下逻辑。但是我注意到分配器的construct
和destroy
成员函数没有关于何时可以和何时不能抛出异常的措辞。
我很确定我以前读过这个词。否则,即使我的类型是nothrow可移动的,construct
仍然可以从用户提供的分配器中抛出异常,比如说,当我调整缓冲区大小以增加容量时。这需要复杂的回滚代码来保证强大的异常安全性,我真的想跳过。
是否有一种措辞只允许从调用ctor/dtor抛出异常,或者分配器总是需要复杂的机制来维护异常安全?
2条答案
按热度按时间qoefvg9y1#
分配器成员可以抛出。如果标准没有说他们不能扔,那么他们可以扔。
但实际上,他们为什么要这样做呢?
特别是对于
std::allocator::construct
和std::allocator::destroy
,它们除了调用构造函数或析构函数之外什么也不做。但是无论如何,您都应该使用std::allocator_traits<Alloc>::construct
和std::allocator_traits<Alloc>::destroy
,如果存在Alloc::construct
/Alloc::destroy
,它们只会调用Alloc::construct
/Alloc::destroy
,否则调用构造函数/析构函数。理论上,病态分配器可以放入这些成员,但您应该假设它们不会。你不能防御病态愚蠢的类型。
u4vypkhs2#
他们的疏忽有一个(或两个)原因。首先,析构函数可以抛出。其次,标准希望避免在有用的上下文中出现未定义的行为。如果他们完全禁止在分配器中抛出
destroy
,那么您就不可能在destroy
函数中拥有一个执行重要工作的分配器。想象一下,在测试中,你可以使用一个分配器来跟踪对象的分配、释放、构造和销毁。在这种情况下,destroy
可能会抛出,因为分配器可能正在引用一些需要存储数据的容器。然而,一个优秀的开发人员应该知道,抛出一个析构函数,或者,在本例中,分配器的destroy
方法,可能会使整个程序的状态无效。因此,在几乎所有情况下,您都可以使用destroy
,因为 * 如果 * 它不会抛出,并且允许未处理的异常/终止。