Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么要求自定义分配器是可复制的?_C++_C++11 - Fatal编程技术网

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

C++ 为什么要求自定义分配器是可复制的?,c++,c++11,C++,C++11,C++11标准(或至少)要求实现分配器概念的类提供拷贝构造函数 这在所有分配器都必须是无状态的时候是有意义的,但在分配器类中允许状态时,提供副本构造函数可能并不可取。例如,如果分配器实现某种板坯分配系统或内存池,则它在其中维护一个内部自由列表。在我看来,这样的分配器应该一直被移动,而不是复制。实际上,复制它需要分配新的存储,然后完全复制原始分配器的内部状态,包括所有可用内存块、可用列表等。(或者“复制”分配器是否仅仅意味着返回分配器(),即返回新的默认构造的分配器?) 实际上,复制一个有状态的分

C++11标准(或至少)要求实现
分配器概念的类提供拷贝构造函数

这在所有分配器都必须是无状态的时候是有意义的,但在分配器类中允许状态时,提供副本构造函数可能并不可取。例如,如果分配器实现某种板坯分配系统或内存池,则它在其中维护一个内部自由列表。在我看来,这样的分配器应该一直被移动,而不是复制。实际上,复制它需要分配新的存储,然后完全复制原始分配器的内部状态,包括所有可用内存块、可用列表等。(或者“复制”
分配器是否仅仅意味着返回
分配器()
,即返回新的默认构造的分配器?)

实际上,复制一个有状态的分配器似乎完全没有必要,因为就我所见,在实践中,复制构造分配器并没有真正的通用用例。没有
Container
实际复制分配器-C++11 containers将调用容器复制构造函数中的
allocator::select_on_Container\u copy\u construction
,它通常只返回
allocator()
。然后,容器通常只需从另一个容器中逐个复制元素,可能只需调用
container::insert

当然,一个优化的容器实现可能会使用关于容器结构的内部知识做一些更复杂的事情,但是仍然没有人会复制构造
other.get\u allocator()
-容器只会调用
other.get\u allocator()。选择容器上的\u\u copy\u construction()
获取默认构造的分配器

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


注:为了清楚起见,这个问题不是重复的。这个问题是专门询问
std::allocator
(无状态),而我询问的是实现
allocator
概念的自定义分配器

没有
容器
实际复制分配器

可能是这样(我还没有测试过),而且
std::string
可能被视为非
容器,但仍然:

#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;
}
#包括
#包括
#include//std::分配器
模板<类类型>
结构分配
:std::分配器
{
使用Base=std::分配器;
模板<类其他>
结构重新绑定
{ 
使用其他=Alloc;
};
Alloc(){}
分配(分配常数和其他)
:基地(其他)
{std::clog int
{
使用名称空间std;
基本字符串a=“a”,b=“b”;
a=b;
}
使用Visual C++进行输出:

Alloc::<copy> Alloc::<copy> Alloc:: Alloc::
使用g++时,分配器复制操作的数量更高。

libc++根本不复制。此外,我认为您应该添加移动构造函数,因为OP声称“移动构造不应该足够吗?”--这并没有改变VS2013和libstdc++的输出,这让人惊讶。知道分配器的容器构造函数不是按const ref获取它们的分配器吗?而且,
get_allocator()
被定义为从C++11之前就返回一个副本,所以只移动一个副本是不起作用的,改变它可能是一个突破性的改变。