将 std::allocate_shared 与多态资源分配器一起使用

Using std::allocate_shared with polymorphic resource allocators

本文关键字:分配器 资源分配 一起 资源 allocate std shared 多态      更新时间:2023-10-16

我正在尝试创建带有std::pmr::monotonic_buffer_resource的共享指针,但我无法对其进行编译。我错过了什么?

https://godbolt.org/z/R9jdju

#include <memory>
#include <memory_resource>
int main() {
char buffer[100];
std::pmr::monotonic_buffer_resource mbr(buffer, 100);
std::shared_ptr<double> sp = std::allocate_shared<double>(mbr);
}
在/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/ext/alloc_traits.h:34 包含的文件中,  来自/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/stl_uninitialized.h:67,  来自/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/memory:66,  来自<来源>:1:/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/alloc_traits.h:替换 'template:7:66:从这里需要/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/alloc_traits.h:78:11:错误:在"struct std::__allocator_traits_base::__rebind<std::p>, void>' 中没有名为"type"的类型  78 |    使用__alloc_rebind |          ^~~~~~~~~~~~~~ 在/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:52 包含的文件中,  来自/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/memory:84,  来自<来源>:1:/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:实例化'std::__shared_count<_Lp>::__shared_count(_Tp*&, std::_Sp_alloc_shared_tag<_Alloc>, _Args&& ...)[_Tp = double; _Alloc = std::p mr::monotonic_buffer_resource; _Args = {}; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]':/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:1371:71:从'std::__shared_ptr<_Tp,_Lp>::__shared_ptr(std::_Sp_alloc_shared_tag<_Tp>,_Args&& ...)中需要[_Alloc = std::p mr::monotonic_buffer_resource; _Args = {}; _Tp = double; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]'/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:408:59:从'std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>,_Args&& ...)中要求[_Alloc = std::p mr::monotonic_buffer_resource; _Args = {}; _Tp = double]'/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:859:14:从'std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...)中需要[_Tp = double; _Alloc = std::p mr::monotonic_buffer_resource; _Args = {}]'<来源>:7:66:从这里需要/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:682:16:错误:使用已删除的函数'std::p mr::monotonic_buffer_resource::monotonic_buffer_resource(const std::p mr::monotonic_buffer_resource&)' 682 |   自动__pi = ::新 (__mem) |               ^~~~~~~~~~~~~ 683 |     _Sp_cp_type(__a._M_a, std::forward<_Args>(__args)...); |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 在从<源>:2 包含的文件中:/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/memory_resource:604:5:注意:在此处声明 604 |    monotonic_buffer_resource(常量 monotonic_buffer_resource&) = 删除; |    ^~~~~~~~~~~~~~~~~~~~~~~~~ 在/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr.h:52 包含的文件中,  来自/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/memory:84,  来自<来源>:1:/opt/compiler-explorer/gcc-10.1.0/include/c++/10.1.0/bits/shared_ptr_base.h:546:33:注意:初始化参数 'std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc, _Args&& ...)[_Args = {}; _Tp = double; _Alloc = std::p mr::monotonic_buffer_resource; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]' 546 | _Sp_counted_ptr_inplace(_Alloc __a、_Args&... __args) |                         ~~~~~~~^~~

这条长错误消息基本上可以归结为以下 2 个错误:

错误:在"结构 std::__allocator_traits_base::__rebind<std::p>、void>"中没有名为"type"的类型

错误:使用已删除的函数"std::p mr::monotonic_buffer_resource::monotonic_buffer_resource(const std::p mr::monotonic_buffer_resource&)">

std::pmr::monotonic_buffer_resource不满足std::allocate_shared()期望的要求,特别是:

所有的内存分配都是使用alloc的副本完成的,它必须满足分配器的要求。

特别是"alloc的副本">,它失败了,因为monotonic_buffer_resource的复制构造函数是delete的,所以它不能被复制。

如@MilesBudnek注释中所述,您可以将monotonic_buffer_resource包装在std::pmr::polymorphic_allocator中,该旨在用作标准容器的Allocator

类模板std::pmr::polymorphic_allocator是一个分配器,它根据构造它的std::pmr::memory_resource表现出不同的分配行为。

例如:

#include <memory>
#include <memory_resource>
int main() {
char buffer[100];
std::pmr::monotonic_buffer_resource mbr(buffer, 100);
auto sp = std::allocate_shared<double, std::pmr::polymorphic_allocator<double>>(&mbr);
}

https://godbolt.org/z/-xFfFY

或者:

#include <memory>
#include <memory_resource>
int main() {
char buffer[100];
std::pmr::monotonic_buffer_resource mbr(buffer, 100);
std::pmr::polymorphic_allocator<double> alloc(&mbr);
auto sp = std::allocate_shared<double>(alloc);
}

https://godbolt.org/z/GLE4-5