Pra*_*ota 3 c++ stl vector map allocator
我有一个关于STL类和分配器的问题,这些问题似乎不容易在网上找到.有谁知道在嵌套的STL类中使用了哪个分配器?例如:
typedef std::vector<int> myvect;
Run Code Online (Sandbox Code Playgroud)
//按照后续回复/评论的指示编辑了以下行
typedef std::map<int, myvect, std::less<int>, A> mymap; //uses my custom allocator for map creation
Run Code Online (Sandbox Code Playgroud)
让我们调用默认的分配器D
,并假设我有一个自定义分配器A
.
如果我做了以下事情将会发生什么:
创建地图:
mymap mapInstance;
Run Code Online (Sandbox Code Playgroud)现在,假设存在一个条目mapInstance[0]
,假设我将一个值推入向量:
mapInstance[0].push_back(999);
Run Code Online (Sandbox Code Playgroud)什么分配器用于向量的动态内存mapInstance[0]
?
到目前为止,我的理解D
是使用了默认分配器,但我想确认A
传入映射的自定义分配器不会被使用.(据我所知,只有我使用某种嵌套分配选项才会发生这种情况.)
当然,我理解mapInstance[0]
使用自定义分配器分配元数据/标头信息A
.我关心的是动态内存部分,即之后的部分d_dataBegin
.
Jon*_*ely 11
你的问题与Scoped Allocator Model有关,它是一种分配器设计风格,它自动将容器的分配器传播到容器的元素,这样你就可以确保所有容器的元素都是从同一个分配器中分配的.更多关于以下内容.
回答你的问题:
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];
Run Code Online (Sandbox Code Playgroud)
然后该条目是默认构造的,并将使用默认构造A1<int>
.
如果该条目是这样创建的:
A1<int> a1( /* args */ );
myvect v(a1)
mapInstance.insert(mymap::value_type(0, v));
Run Code Online (Sandbox Code Playgroud)
然后该条目将是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;
Run Code Online (Sandbox Code Playgroud)
然后向量被复制分配给,可能会替换分配器,具体取决于值std::allocator_traits<A1<int>>::propagate_on_container_copy_assignment::value
如果该条目被修改如下:
A1<int> a1( /* args */ );
mapInstance[0] = myvect(a1);
Run Code Online (Sandbox Code Playgroud)
然后向量移动分配给,可能会取代分配器,具体取决于std::allocator_traits<A1<int>>::propagate_on_container_move_assignment::value
如果该条目被修改如下:
A1<int> a1( /* args */ );
myvect v(a1)
swap( mapInstance[0], v );
Run Code Online (Sandbox Code Playgroud)
然后交换向量,这可能会取代分配器,具体取决于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];
Run Code Online (Sandbox Code Playgroud)
然后,而不是默认构造的条目,scoped_allocator_adaptor
将使用地图的分配器的副本构造它,因此条目将被构造为myvect( A1<int>(mapInstance.get_allocator()) )
.
如果该条目是这样创建的:
A1<int> a1( /* args */ );
myvect v(a1)
mapInstance.insert(mymap::value_type(0, v));
Run Code Online (Sandbox Code Playgroud)
然后该条目将有一个v
数据的副本,但不会使用它的分配器,而是由它传递一个分配器scoped_allocator_adaptor
,因此将构造如下:myvect( v, A1<int>(mapInstance.get_allocator()) )
.
如果这有点令人困惑,欢迎来到我的世界,但不要担心,在你的情况下vector<int>
将永远使用std::allocator<int>
.
归档时间: |
|
查看次数: |
870 次 |
最近记录: |