这里说是因为异常规范。我不明白。这个问题与异常规范有什么关系吗?
4 回答
阅读完教程后,我对措辞感到有些困惑。但我相信它就像这样简单:教程解释了为什么分配器的模板标题显示
allocator(const allocator&) throw();
和
template <class U> allocator(const allocator<U>&) throw();
即使复制构造函数对于分配器来说毫无用处。答案是分配器的规范不允许构造函数抛出异常。因此,复制构造函数公共接口定义了具有异常规范的复制构造函数throw()
(不抛出任何异常),以防止有人使用可能抛出异常的复制构造函数派生自己的分配器。
请参阅此链接以很好地描述异常规范是什么,如果这就是抛出你的原因。(没有双关语。真的。)
因此,它们并不是说在创建分配器时,您必须提供一个复制构造函数。他们只是指出该规范明确禁止您定义一个引发任何异常的规范。`
您必须显式编写复制构造函数(而不是使用默认值),因为 C++03 分配器的复制构造函数需要使用异常说明符定义throw()
。默认的复制构造函数没有这个说明符。
从技术上讲,你不必这样做,但如果它确实引发了异常......好吧,祝你好运。
但这只是一个小麻烦,因为 C++03 中的分配器不能有状态。所以你不应该复制成员。复制构造函数可以为空。
分配器需要一个复制构造函数,因为容器有一个复制构造函数,并且需要在这个过程中复制它们的分配器。
其实很简单。使用分配器的容器的构造函数获取分配器并存储它的副本。为了做到这一点,它需要分配器是CopyConstructible
. 就这样。请注意,分配器类型不需要,CopyAssignable
除非其propagate_on_container_copy_assignment
特征为真(这很少见)。
C++11 规范还声明“对这些类型的任何构造函数、比较运算符、复制操作、移动操作或交换操作都不应通过异常退出。” 异常规则允许您制作分配器的(堆栈)副本(尤其是在构造或销毁期间),而不必担心复制分配器会抛出异常。在存在可能引发复制、移动、交换或比较的分配器的情况下设计异常安全的容器几乎是不可能的。在实践中,分配器只能保存指向某些资源的指针,因此允许分配器抛出副本等会增加很多痛苦而几乎没有收获。