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

标签 c++ stl

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

list<int, my_allocator<int> > data;

然后我可以使用更高效的分配器,比方说内存池。但是list不需要像前向指针和后向指针一样分配内部内存来遍历list吗?这些将如何分配?使用普通的 new 还是以某种方式使用 my_allocator

最佳答案

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

typedef typename Alloc::template rebind<MyInternalStuff>::other internal_allocator;

如果您的分配器是 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,它在构造时打印自己的类型名。这是输入:

#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 } };
}

这里是输出:

----- 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> > >

细节因使用的构造函数而异:容器如 setmap可能只在某些调用中构造“正确的”分配器,而在另一个调用中,它们可能首先构造指定分配器的对象。无论哪种方式,指定的分配器根本不会用于几个容器,并且使用回弹版本。

关于c++ - STL 中的自定义分配器是否只分配实际数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8556004/

相关文章:

c++ - 基类函数被调用两次

c++ - 找出装箱问题的所有可能变化

c++ - fscanf 和结构对齐

用于分布式计算的 C++ 与 C

c++ - C++ 中的容器和运算符

c++ - 在 map : How to clear inner map using iterators? 中映射

c++ - 将参数传递给 C++ 中的无操作宏

c++ - 如何从priority_queue中删除不在顶部的元素?

c++ - 带有标准容器的 unique_ptr : attempting to reference a deleted function

c++ - "UTF-16"和 "std::wstring"有什么区别?