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