polymorphic_allocator:我何时以及为什么要使用它? [英] polymorphic_allocator: when and why should I use it?

查看:162
本文介绍了polymorphic_allocator:我何时以及为什么要使用它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此处 cppreference 上的文档,此处是工作草案。



我必须承认我不了解 polymorphic_allocator 的真正目的是什么以及何时/为什么/如何使用它。

例如, pmr :: vector 具有以下签名:

 命名空间pmr {
template< class T>
使用vector = std :: vector< T,polymorphic_allocator< T> ;;
}

polymorphic_allocator 报价?关于老式的 std :: vector std :: pmr :: vector 有什么作用? ?
直到现在我还无法做我现在该怎么办?

该分配器的真正目的是什么,我什么时候应该实际使用它?

解决方案

从cppreference中选择报价:


此运行时多态性允许对象使用尽管具有相同的静态分配器类型,polymorphic_allocator的行为就像在运行时使用了不同的分配器类型一样


常规分配器的问题是他们改变了容器的类型。如果要使用带有特定分配器的 vector ,则可以使用 Allocator 模板参数:

  auto my_vector = std :: vector< int,my_allocator>(); 

现在的问题是,此向量与具有不同分配器的向量类型不同。例如,您不能将其传递给需要默认分配器向量的函数,也不能将两个具有不同分配器类型的向量分配给同一变量/指针,例如:

  auto my_vector = std :: vector< int,my_allocator>(); 
auto my_vector2 = std :: vector< int,other_allocator>();
auto vec = my_vector; //好的
vec = my_vector2; //错误

多态分配器是单个分配器类型,其成员可以通过以下方式定义分配器行为动态分配,而不是通过模板机制。这样,您就可以使用特定的,自定义分配的容器,但是它们仍然是普通类型。



分配器行为的自定义是通过给分配器一个 std :: memory_resource *

  //通过自定义定义分配行为 memory_resource 
class my_memory_resource:public std :: pmr :: memory_resource {...};
my_memory_resource mem_res;
auto my_vector = std :: pmr :: vector< int>(0,& mem_res);

//定义第二个内存资源
类other_memory_resource:public std :: pmr :: memory_resource {...};
other_memory_resource mem_res_other;
auto my_other_vector = std :: pmr :: vector< int>(0,& mes_res_other);

auto vec = my_vector; //类型为std :: pmr :: vector< int>
vec = my_other_vector; //这没关系-
// my_vector和my_other_vector具有相同的类型

如我所见,问题是 std :: pmr :: 容器仍然与等效的 std :: 容器使用默认分配器。设计与容器一起使用的接口时,您需要做出一些决定:




  • 是否有可能容器传入了?需要自定义分配吗?

  • 如果这样,我应该添加模板参数(以允许使用任意分配器)还是应该强制使用多态分配器?



模板解决方案允许任何分配器,包括多态分配器,但是还有其他缺点(生成的代码大小,编译时间,代码必须暴露在头文件中,则可能会进一步导致类型污染,从而继续将问题向外推。另一方面,多态分配器解决方案要求必须使用多态分配器 。这排除了使用使用默认分配器的 std :: 容器,并且可能会影响与旧代码的接口。




Here is the documentation on cppreference, here is the working draft.

I must admit that I didn't understand what's the real purpose of polymorphic_allocator and when/why/how I should use it.
As an example, the pmr::vector has the following signature:

namespace pmr {
    template <class T>
    using vector = std::vector<T, polymorphic_allocator<T>>;
}

What does the polymorphic_allocator offer? What does the std::pmr::vector offer as well in regard of the old-fashioned std::vector? What can I do now that I wasn't able to do till now?
What's the real purpose of that allocator and when should I use it actually?

解决方案

Choice quote from cppreference:

This runtime polymorphism allows objects using polymorphic_allocator to behave as if they used different allocator types at run time despite the identical static allocator type

The issue with "regular" allocators is that they change the type of the container. If you want a vector with a specific allocator, you can make use of the Allocator template parameter:

auto my_vector = std::vector<int,my_allocator>();

The problem now is that this vector is not the same type as a vector with a different allocator. You can't pass it to a function which requires a default-allocator vector, for example, or assign two vectors with a different allocator type to the same variable / pointer, eg:

auto my_vector = std::vector<int,my_allocator>();
auto my_vector2 = std::vector<int,other_allocator>();
auto vec = my_vector; // ok
vec = my_vector2; // error

A polymorphic allocator is a single allocator type with a member that can define the allocator behaviour via dynamic dispatch rather than through the template mechanism. This allows you to have containers which use specific, customised allocation, but which are still of a common type.

The customisation of allocator behavior is done by giving the allocator a std::memory_resource *:

// define allocation behaviour via a custom "memory_resource"
class my_memory_resource : public std::pmr::memory_resource { ... };
my_memory_resource mem_res;
auto my_vector = std::pmr::vector<int>(0, &mem_res);

// define a second memory resource
class other_memory_resource : public std::pmr::memory_resource { ... };
other_memory_resource mem_res_other;
auto my_other_vector = std::pmr::vector<int>(0, &mes_res_other);

auto vec = my_vector; // type is std::pmr::vector<int>
vec = my_other_vector; // this is ok -
      // my_vector and my_other_vector have same type

The main remaining issue, as I see it, is that a std::pmr:: container is still not compatible with the equivalent std:: container using the default allocator. You need to make some decisions at the time you design an interface which works with a container:

  • is it likely that the container passed in may require custom allocation?
  • if so, should I add a template parameter (to allow for arbitrary allocators) or should I mandate the use of a polymorphic allocator?

A template solution allows for any allocator, including a polymorphic allocator, but has other drawbacks (generated code size, compile time, code must be exposed in header file, potential for further "type contamination" which keeps pushing the problem outward). A polymorphic allocator solution on the other hand dictates that a polymorphic allocator must be used. This precludes using std:: containers which use the default allocator, and might have implications for interfacing with legacy code.

Compared to a regular allocator, a polymorphic allocator does have some minor costs, such as the storage overhead of the memory_resource pointer (which is most likely negligible) and the cost of virtual function dispatch for allocations. The main problem, really, is probably lack of compatibility with legacy code which doesn't use polymorphic allocators.

这篇关于polymorphic_allocator:我何时以及为什么要使用它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆