polymorphic_allocator:何时以及为什么要使用它?

时间:2022-04-01 07:09:02

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

这是关于cppreference的文档,这是工作草案。

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:

我必须承认,我不明白polymorphic_allocator的真正目的是什么,以及何时/为什么/如何使用它。例如,pmr :: vector具有以下签名:

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?

polymorphic_allocator提供什么?对于老式的std :: vector,std :: pmr :: vector提供了什么?我现在能做什么才能做到现在为止?分配器的真正目的是什么?我应该何时使用它?

2 个解决方案

#1


42  

Choice quote from cppreference:

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

尽管具有相同的静态分配器类型,但此运行时多态性允许使用polymorphic_allocator的对象在运行时使用不同的分配器类型。

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:

“常规”分配器的问题是它们改变了容器的类型。如果需要具有特定分配器的向量,可以使用Allocator模板参数:

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

通过为分配器提供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:

正如我所看到的,主要的剩余问题是std :: pmr :: container仍然与使用默认分配器的等效std :: 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.

模板解决方案允许任何分配器,包括多态分配器,但具有其他缺点(生成的代码大小,编译时间,代码必须暴露在头文件中,可能导致进一步的“类型污染”,从而不断向外推送问题)。另一方面,多态分配器解决方案规定必须使用多态分配器。这排除了使用使用默认分配器的std :: containers,并且可能会影响与遗留代码的接口。

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.

与常规分配器相比,多态分配器确实具有一些较小的成本,例如memory_resource指针的存储开销(最可能忽略不计)和分配的虚拟函数调度的成本。实际上,主要问题可能是缺乏与不使用多态分配器的遗留代码的兼容性。

#2


17  

polymorphic_allocator is to a custom allocator as std::function is to a direct function call.

polymorphic_allocator是自定义分配器,因为std :: function是直接函数调用。

It simply lets you use an allocator with your container without having to decide, at the point of declaration, which one. So if you have a situation where more than one allocator would be appropriate, you can use polymorphic_allocator.

它只是让你在容器中使用一个分配器,而不必在声明时决定哪一个。因此,如果您有一个适合多个分配器的情况,您可以使用polymorphic_allocator。

Maybe you want to hide which allocator is used to simplify your interface, or maybe you want to be able to swap it out for different runtime cases.

也许您想要隐藏哪个分配器用于简化您的界面,或者您希望能够将其交换出来用于不同的运行时案例。

First you need code that needs an allocator, then you need to want to be able to swap which one is used, before considering pmr vector.

首先,您需要需要分配器的代码,然后在考虑pmr向量之前,您需要能够交换使用哪个代码。

#1


42  

Choice quote from cppreference:

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

尽管具有相同的静态分配器类型,但此运行时多态性允许使用polymorphic_allocator的对象在运行时使用不同的分配器类型。

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:

“常规”分配器的问题是它们改变了容器的类型。如果需要具有特定分配器的向量,可以使用Allocator模板参数:

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

通过为分配器提供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:

正如我所看到的,主要的剩余问题是std :: pmr :: container仍然与使用默认分配器的等效std :: 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.

模板解决方案允许任何分配器,包括多态分配器,但具有其他缺点(生成的代码大小,编译时间,代码必须暴露在头文件中,可能导致进一步的“类型污染”,从而不断向外推送问题)。另一方面,多态分配器解决方案规定必须使用多态分配器。这排除了使用使用默认分配器的std :: containers,并且可能会影响与遗留代码的接口。

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.

与常规分配器相比,多态分配器确实具有一些较小的成本,例如memory_resource指针的存储开销(最可能忽略不计)和分配的虚拟函数调度的成本。实际上,主要问题可能是缺乏与不使用多态分配器的遗留代码的兼容性。

#2


17  

polymorphic_allocator is to a custom allocator as std::function is to a direct function call.

polymorphic_allocator是自定义分配器,因为std :: function是直接函数调用。

It simply lets you use an allocator with your container without having to decide, at the point of declaration, which one. So if you have a situation where more than one allocator would be appropriate, you can use polymorphic_allocator.

它只是让你在容器中使用一个分配器,而不必在声明时决定哪一个。因此,如果您有一个适合多个分配器的情况,您可以使用polymorphic_allocator。

Maybe you want to hide which allocator is used to simplify your interface, or maybe you want to be able to swap it out for different runtime cases.

也许您想要隐藏哪个分配器用于简化您的界面,或者您希望能够将其交换出来用于不同的运行时案例。

First you need code that needs an allocator, then you need to want to be able to swap which one is used, before considering pmr vector.

首先,您需要需要分配器的代码,然后在考虑pmr向量之前,您需要能够交换使用哪个代码。