STL中的自定义分配器是否只分配实际数据?

Pet*_*ter 7 c++ stl

假设我在STL中创建了一个链表:

list<int, my_allocator<int> > data;
Run Code Online (Sandbox Code Playgroud)

然后我可以使用更有效的分配器,假设一个内存池.但是列表是否需要分配内部存储器,如前向和后向指针来遍历列表?这些如何分配?使用正常new或以某种方式使用my_allocator

Ker*_* SB 11

容器确实重新调整了分配器的用途,以分配自己的簿记材料.(并不是说它对于a来说很重要std::list,但它一般都是正确的.*)这就是标准分配器要求强制存在rebind模板的原因:

typedef typename Alloc::template rebind<MyInternalStuff>::other internal_allocator;
Run Code Online (Sandbox Code Playgroud)

如果你的分配器是Alloc = my_allocator<T>,那就internal_allocator变成了my_allocator<MyInternalStuff>.

我相信这是Electronic Arts对C++标准库的抱怨之一,这就是为什么他们的EASTL库使用不同的分配器约定来提供更严格的控制.

*)典型地,每个节点将是某种类型的一个单片对象Node<T>,所以我想std::list<T, Alloc> 曾经使用Alloc::rebind<Node<T>>::other作为分配器.

[抱歉进行了多次编辑; 我的输出被破坏了,并没有正确解释它; 我现在单独打印每个容器并相应地固定输出.std::list确实只需要一个分配器.]


更新:只是为了咯咯笑,我写了一个小的demangling-allocator,在构造时打印自己的typename.这是输入:

#include <unordered_map>
#include <set>
#include <deque>
#include <list>
#include <vector>
#include <map>

#include <iostream>

int main()
{
  std::cout << "----- unordered_map<int, double> -----------" << std::endl;
  std::unordered_map<int, double, std::hash<int>, std::equal_to<int>, funky_allocator<std::pair<const int, double>>> m { {1, 1.2} };
  std::cout << "----- set<int> -----------------------------" << std::endl;
  std::set<int, std::less<int>, funky_allocator<int>> s;
  std::cout << "----- deque<int> ---------------------------" << std::endl;
  std::deque<int, funky_allocator<int>> d;
  std::cout << "----- list<int> ----------------------------" << std::endl;
  std::list<int, funky_allocator<int>> l;
  std::cout << "----- vector<int> --------------------------" << std::endl;
  std::vector<int, funky_allocator<int>> c;
  std::cout << "----- map<int, bool> -----------------------" << std::endl;
  std::map<int, bool, std::less<int>, funky_allocator<std::pair<const int, bool>>> n { { 1, true } };
}
Run Code Online (Sandbox Code Playgroud)

在这里输出:

----- unordered_map<int, double> -----------
Default-construct: funky_allocator<std::pair<int const, double> >
Copy-construct:    funky_allocator<std::__detail::_Hash_node<std::pair<int const, double>, false> >
Copy-construct:    funky_allocator<std::__detail::_Hash_node<std::pair<int const, double>, false>*>

----- set<int> -----------------------------
Default-construct: funky_allocator<std::_Rb_tree_node<int> >

----- deque<int> ---------------------------
Default-construct: funky_allocator<int>
Copy-construct:    funky_allocator<int*>

----- list<int> ----------------------------
Default-construct: funky_allocator<std::_List_node<int> >

----- vector<int> --------------------------
Default-construct: funky_allocator<int>

----- map<int, bool> -----------------------
Default-construct: funky_allocator<std::_Rb_tree_node<std::pair<int const, bool> > >
Run Code Online (Sandbox Code Playgroud)

细节取决于使用的构造函数:容器喜欢set并且map可能只在某些调用中构造"正确"的分配器,而在另一个调用器中,它们可能首先构造指定分配器的对象.无论哪种方式,指定的分配器永远不会被用于几个容器,并且使用反弹版本.