分配嵌套 STL 容器时使用哪个分配器
Which allocator is used when allocating a nested STL container?
我有一个关于STL类和分配器的问题,在网上似乎不容易找到。有谁知道嵌套 STL 类中使用了哪个分配器?例如:
typedef std::vector<int> myvect;
下面的行是按照后续回复/评论所指出的编辑的
typedef std::map<int, myvect, std::less<int>, A> mymap; //uses my custom allocator for map creation
让我们调用默认分配器D
,并假设我有一个自定义分配器A
。
如果我执行以下操作会发生什么:
创建地图:
mymap mapInstance;
现在,假设存在一个
mapInstance[0]
条目,假设我将一个值推入向量:mapInstance[0].push_back(999);
什么分配器用于矢量mapInstance[0]
的动态存储器?
到目前为止,我的理解是使用默认分配器D
,但我想确认没有使用传递给地图的自定义分配器A
。(据我所知,这只有在我使用某种嵌套分配选项时才会发生。
当然,我知道mapInstance[0]
的元数据/标头信息是使用自定义分配器A
分配的。我关心的是动态内存部分,即d_dataBegin
之后的部分。
您的问题与作用域分配器模型有关,这是一种分配器设计样式,可自动将容器的分配器传播到容器的元素,以便您可以确保容器的所有元素都从同一分配器分配。更多内容见下文。
要回答您的问题:
1) 默认情况下,容器不使用作用域分配器模型,您必须显式请求它(请参阅下面的scoped_allocator_adaptor
)
2)您的嵌套容器是类型std::vector<int>
这意味着它使用默认的std::allocator<int>
分配器,并且该类型的所有实例都是相同的,因此您的问题的答案是它使用标准分配器 - 哪一个并不重要,因为每个std::allocator<int>
都是一样的。
这个答案的其余部分只是一个思想实验,你的问题的答案在上面:vector<int>
总是使用std::allocator<int>
现在,如果您的嵌套类型std::vector<int, A1<int>>
其中A1<int>
是自定义分配器,那么问题会变得更加有趣。
嵌套容器将使用它所构造的分配器,而您还没有证明这一点,因为您已经说过">假设存在mapInstance[0]
条目",并且该条目的创建方式决定了它将使用哪个分配器。
如果该条目是按如下所示创建的:
mapInstance[0];
则该条目是默认构造的,并将使用默认构造的A1<int>
。
如果该条目是按如下所示创建的:
A1<int> a1( /* args */ );
myvect v(a1)
mapInstance.insert(mymap::value_type(0, v));
然后条目将是v
的副本,在 C++03 中,它的分配器将是v.get_allocator()
的副本,但在 C++11 中,它的分配器将是std::allocator_traits<A1<int>>::select_on_container_copy_construction(v.get_allocator())
的副本,这可能是v.get_allocator()
的副本,但可能是不同的(例如默认构造的A1
)。
(在 C++03 中,条目的分配器在创建后无法更改,因此答案将在此处结束,但在 C++11 中可以替换它。我假设我们在这个问题的其余部分谈论C++11,因为分配器在C++03中不是很有趣。
如果该条目按如下所示修改:
A1<int> a1( /* args */ );
myvect v(a1)
mapInstance[0] = v;
然后向量被复制分配给,这可能会取代分配器,具体取决于std::allocator_traits<A1<int>>::propagate_on_container_copy_assignment::value
的值
如果该条目按如下所示修改:
A1<int> a1( /* args */ );
mapInstance[0] = myvect(a1);
然后向量被移动到,这可能会取代分配器,具体取决于std::allocator_traits<A1<int>>::propagate_on_container_move_assignment::value
如果该条目按如下所示修改:
A1<int> a1( /* args */ );
myvect v(a1)
swap( mapInstance[0], v );
然后交换向量,这可能会取代分配器,具体取决于std::allocator_traits<A1<int>>::propagate_on_container_swap::value
的值
现在,如果A
std::scoped_allocator_adaptor<A1<std::pair<const int, myvect>>>
事情变得更加有趣! 顾名思义,scoped_allocator_adaptor
是一个适配器,它允许任何分配器类型与作用域分配器模型一起使用,这意味着容器的分配器可以传递给容器的子项及其子项的子项等(只要这些类型使用分配器并且可以使用它们构造)。
默认情况下,容器和分配器不使用需要使用的作用域分配器模型scoped_allocator_adaptor
(或编写自己的分配器类型,其工作原理相同)来使用它。 (C++03 完全不支持作用域分配器。
如果该条目是按如下所示创建的:
mapInstance[0];
然后,scoped_allocator_adaptor
将使用地图分配器的副本构造它,而不是默认构造的条目,因此该条目将像myvect( A1<int>(mapInstance.get_allocator()) )
一样构造。
如果该条目是按如下所示创建的:
A1<int> a1( /* args */ );
myvect v(a1)
mapInstance.insert(mymap::value_type(0, v));
然后条目将有v
数据的副本,但不会使用其分配器,相反,它将由scoped_allocator_adaptor
传递一个分配器,因此将构造为:myvect( v, A1<int>(mapInstance.get_allocator()) )
。
如果这一切都有点令人困惑,欢迎来到我的世界,但不要担心,在您的情况下,vector<int>
将始终使用std::allocator<int>
.
默认分配器D
用于push_back
调用。
事实上,默认分配器也用于map
,因为容器的类型指定使用默认分配器。假设您的A
继承自std::allocator
,所发生的只是您的分配器被切片为默认分配器,并且容器的行为就像您根本没有传递分配器实例一样。
- 嵌套在类中时无法设置成员数据
- 无法访问嵌套类.类的使用无效
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 如何在C++中初始化嵌套类中的2个memeber
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 在C++中搜索嵌套多映射值
- 在C++中将矢量转换为嵌套地图
- C++嵌套if语句,基本货币交换
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 嵌套的匿名命名空间
- 了解嵌套循环打印星号图案
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 嵌套for循环C++的问题(初学者)
- 从嵌套在std::映射中的std::列表中删除元素的最佳方式
- 用C#中的并集模拟C++嵌套结构
- 部分专业化和嵌套模板
- 嵌套While循环不起作用(C++问题)
- C++-模板嵌套类的引用初始化无效
- 如何在嵌套类中正确使用友元声明?
- 分配嵌套 STL 容器时使用哪个分配器