为什么自定义分配器的要求是可复制的?

Sil*_*ler 10 c++ c++11

C++ 11标准(或至少是本工作草案)要求实现该Allocator概念的类提供复制构造函数.

当所有分配器都必须是无状态时,这有意义,但是当在分配器类中允许状态时,提供复制构造函数可能并不可取.例如,如果分配器实现某种slab分配系统或内存池,则它维护一个内部freelist.在我看来,应该始终移动这样的分配器,而不是复制.实际上复制它需要分配新的存储,然后完全复制原始分配器的内部状态,包括所有空闲内存块,空闲列表等.(或者"复制" Allocator只是意味着返回Allocator(),即返回一个新的默认构造分配器?)

实际上复制一个有状态的分配器似乎是完全没有必要的,因为据我所知,实际上没有真正的通用用例来复制构造一个分配器.Container实际上没有复制分配器--C++ 11容器将Allocator::select_on_container_copy_construction在容器拷贝构造函数中调用,而这通常只返回Allocator().然后容器通常只是从另一个容器中逐个元素地复制,可能只是通过调用Container::insert.

当然,优化的容器实现可能会使用有关容器结构的内部知识来执行更复杂的操作,但仍然没有人会复制构造other.get_allocator()- Container将只调用other.get_allocator().select_on_container_copy_construction()以获取默认构造的分配器.

那么为什么我们要求分配器本身必须是可复制构造的呢?不应该移动施工是否足够?


注意:要清楚,这个问题与c ++中的allocator为什么需要复制构造函数重复.那个问题是专门询问std::allocator(这是无状态的),而我问的是实现这个Allocator概念的自定义分配器.

Che*_*Alf 1

重新索赔

实际上 没有Container复制分配器

可能是这样(我没有测试过),并且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;
}
Run Code Online (Sandbox Code Playgroud)

使用 Visual C++ 输出:

分配::<副本>
分配::<副本>

使用 g++ 时,分配器复制操作的数量会更高。