C++11 标准(或至少 this working draft)要求实现 Allocator
概念的类提供复制构造函数。
这在所有分配器都必须是无状态的时候是有意义的,但是当分配器类中允许有状态时,可能不需要提供复制构造函数。例如,如果分配器实现了某种 slab 分配系统或内存池,它会在其中维护一个内部空闲列表。在我看来,这样的分配器应该总是被移动,而不是被复制。实际上复制它需要分配新的存储,然后完全复制原始分配器的内部状态,包括所有空闲内存块、空闲列表等。(或者“复制”一个 Allocator
只是意味着返回Allocator()
,即返回一个新的默认构造的分配器?)
实际上,复制一个有状态的分配器似乎完全没有必要,因为据我所知,在实践中,复制构造分配器并没有真正常见的用例。没有 Container
实际上复制分配器 - C++11 容器将在容器复制构造函数中调用 Allocator::select_on_container_copy_construction
,通常只返回 Allocator()
。然后容器通常会从另一个容器中逐个元素地复制,可能只是调用 Container::insert
。
当然,优化的容器实现可能会使用有关容器结构的内部知识来做一些更复杂的事情,但仍然没有人会复制构造 other.get_allocator()
- 容器只会调用 other.get_allocator().select_on_container_copy_construction()
获取默认构造的分配器。
那么为什么我们要求分配器本身必须是可复制构造的?搬家 build 还不够吗?
注意:明确地说,这个问题不是 why does allocator in c++ need a copy constructor? 的拷贝.这个问题专门询问 std::allocator
(它是无状态的),而我问的是实现 Allocator
概念的自定义分配器。
最佳答案
再 claim
” No
Container
actually copies an allocator
可能是这样(我没测试过),std::string
可能被认为是一个非Container
,但仍然:
#include <string>
#include <iostream>
#include <memory> // std::allocator
template< class Type >
struct Alloc
: std::allocator<Type>
{
using Base = std::allocator<Type>;
template< class Other >
struct rebind
{
using other = Alloc<Other>;
};
Alloc() {}
Alloc( Alloc<Type> const& other )
: Base( other )
{ std::clog << "Alloc::<copy>\n"; }
template<class Other>
Alloc( Alloc<Other> const& other )
: Base( other )
{ std::clog << "Alloc::<generic-copy>\n"; }
};
auto main() -> int
{
using namespace std;
basic_string< char, char_traits<char>, Alloc<char> > a = "A", b = "B";
a = b;
}
用 Visual C++ 输出:
Alloc::<copy> Alloc::<copy>
对于 g++,分配器复制操作的数量更多。
关于c++ - 为什么要求自定义分配器是可复制构造的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27462075/