首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >std::scoped_allocator_adaptor的用途是什么?

std::scoped_allocator_adaptor的用途是什么?
EN

Stack Overflow用户
提问于 2014-03-03 21:37:54
回答 1查看 3.7K关注 0票数 32

在C++11标准中,我们在动态内存管理库中有std::scoped_allocator_adaptor。这个类最重要的用例是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-12 18:37:44

如果你想要一个字符串容器,并且想对容器和它的元素使用相同的分配器(就像TemplateRex描述的那样,它们都被分配在同一个竞技场中),那么你可以手动完成:

代码语言:javascript
复制
template<typename T>
  using Allocator = SomeFancyAllocator<T>;
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
using Vector = std::vector<String, Allocator<String>>;

Allocator<String> as( some_memory_resource );
Allocator<char> ac(as);
Vector v(as);
v.push_back( String("hello", ac) );
v.push_back( String("world", ac) );

但是,这很笨拙且容易出错,因为很容易意外插入不使用相同分配器的字符串:

代码语言:javascript
复制
v.push_back( String("oops, not using same memory resource") );

std::scoped_allocator_adaptor的目的是自动将分配器传播到它构造的对象,如果这些对象支持使用分配器构造的话。因此,上面的代码将变成:

代码语言:javascript
复制
template<typename T>
  using Allocator = SomeFancyAllocator<T>;
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
using Vector = std::vector<String, std::scoped_allocator_adaptor<Allocator<String>>>;
                                   /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
Allocator<String> as( some_memory_resource );
Allocator<char> ac(as);
Vector v(as);
v.push_back( String("hello") );  // no allocator argument needed!
v.push_back( String("world") );  // no allocator argument needed!

现在,向量的分配器被自动用于构造它的元素,即使插入的对象String("hello")String("world")不是用相同的分配器构造的。由于可以从const char*隐式构造basic_string,因此可以进一步简化最后两行:

代码语言:javascript
复制
v.push_back( "hello" );
v.push_back( "world" );

这更简单,更容易阅读,更不容易出错,这要归功于scoped_allocator_adaptor使用向量的分配器自动构造元素。

当向量请求其分配器构造一个元素作为obj的副本时,它调用:

代码语言:javascript
复制
std::allocator_traits<allocator_type>::construct( get_allocator(), void_ptr, obj );

通常情况下,分配器的construct()成员会调用如下内容:

代码语言:javascript
复制
::new (void_ptr) value_type(obj);

但是如果allocator_typescoped_allocator_adaptor<A>,那么它将使用模板元编程来检测是否可以使用适应类型的分配器来构造value_type。如果value_type没有在其构造函数中使用分配器,那么适配器就会使用:

代码语言:javascript
复制
std::allocator_traits<outer_allocator_type>::construct(outer_allocator(), void_ptr, obj);

这将调用嵌套分配器的construct()成员,该成员使用像上面这样的placement new。但是,如果对象支持在其构造函数中使用分配器,则scoped_allocator_adaptor<A>::construct()可以:

代码语言:javascript
复制
std::allocator_traits<outer_allocator_type>::construct(outer_allocator(), void_ptr, obj, inner_allocator());

或者:

代码语言:javascript
复制
std::allocator_traits<outer_allocator_type>::construct(outer_allocator(), void_ptr, std::allocator_arg, inner_allocator(), obj);

也就是说,当适配器在其嵌套的分配器上调用construct()时,它会传递额外的参数,以便使用分配器构造对象。inner_allocator_typescoped_allocator_adaptor的另一个特化,所以如果元素类型也是一个容器,它使用相同的协议来构造它的元素,并且分配器可以向下传递到每个元素,即使你有容器等等。

因此,适配器的目的是包装现有的分配器,并执行所有元编程和构造函数参数的操作,以将分配器从容器传播到其子容器。

票数 46
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22148258

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档