英文:
Is it possible to bundle "runtime" allocator information with an allocator in C++?
问题
当我们为C++中的std::vector
提供分配器时,请注意我们提供的是一个类分配器。类无法在运行时创建。
但是,如果我需要我的分配器依赖于运行时信息呢?例如,我们可能需要确定如何从特定用户输入分配内存。或者,如果我们想通过使用来自mmap
文件的虚拟内存来创建向量,但在编译时不知道文件的情况下,那么我们也需要这个。当然,我们可以使用全局变量来实现这一点,但这显然不是一个好方法。
是否有可能在使用std::vector
时存储这种运行时信息呢?
这个问题非常简单。然而,经过查找,我发现没有任何答案。显然,没有优雅的方法来实现这一点。
英文:
When we supply an allocator for std::vector
in C++, note that we supply an allocator class. A class cannot be created at runtime.
However, what if I need my allocator to depends on runtime information? For example, we might need to determine how to allocate from the particular user input. Or, if we want to create a vector by using virtual memory from mmap
ing a file, but the file is not known at compile time, then we also need this. Surely we can use global variables for this, but surely that's not a good way.
Is it possible to store such runtime information in the use of std::vector
?
The question is simple enough. However, after looking around, I see no answers at all. Apparently there are no elegant ways to do this?
答案1
得分: 1
这听起来你正在寻找 std::pmr::polymorphic_allocator
,它是一个从 std::pmr::memory_resource
构造的分配器(实际上是一个分配器)。这允许你在运行时有效地选择分配器。
英文:
It sounds like you're looking for std::pmr::polymorphic_allocator
, which is an allocator that is constructed from a std::pmr::memory_resource
(which is effectively an allocator). This lets you effectively choose the allocator at runtime.
答案2
得分: 1
是的,这是可能的。标准库中的所有容器都满足 allocator-aware 要求。简单来说,这意味着容器必须将分配器存储为一个子对象,并在容器被复制、移动等操作时正确处理该对象。有两种实现有状态分配器的方法:
有状态的静态分配器
template <typename T>
struct mmap_allocator { /* ... */ };
mmap_allocator<data> create_mmap_allocator(std::string_view file) { /* ... */ }
auto create_vec() {
std::vector<data, mmap_allocator<data>> result(create_mmap_allocator());
/* ... */
return result;
}
mmap_allocator
可以存储状态,比如已打开的文件是哪个,映射内存的指针等。一个明显的缺点是,这个 std::vector
现在与普通的 std::vector
不同,因为它使用了自定义的分配器。
多态分配器
如果你想要更多的自定义,比如在同一类型的向量中使用完全不同类型的分配器,这会变得繁琐。std::vector<T>
和 std::vector<T, mmap_allocator<T>>
不兼容也很烦人。为了解决这个问题,有多态分配器:
struct mmap_resource : std::pmr::memory_resource { /* ... */ };
mmap_resource create_mmap_resource(std::string_view file) {
/* ... */
}
auto use_vec() {
// TODO: 分配器不拥有内存资源,所以
// 我们可能需要将向量和资源捆绑在一起
// 在一个结构中等等。
auto resource = create_mmap_resource(...);
std::pmr::polymorphic_allocator alloc = &resource;
std::pmr::vector<data> result(alloc);
/* ... */
}
多态分配器是 std::pmr::memory_resource
的多态类包装器,你可以进行自定义。
还可以参考:polymorphic_allocator: when and why should I use it?
英文:
Yes, it's possible. All containers in the standard library satisfy the allocator-aware requirement. In simple terms, this means that the container has to store an allocator as a subobject, and handle this object correctly when the container is copied, moved, etc. There are two approaches to implementing stateful allocators:
Stateful Static Allocators
template <typename T>
struct mmap_allocator { /* ... */ };
mmap_allocator<data> create_mmap_allocator(std::string_view file) { /* ... */ }
auto create_vec() {
std::vector<data, mmap_allocator<data>> result(create_mmap_allocator());
/* ... */
return result;
}
mmap_allocator
can store state, such as which file was opened, a pointer to the mapped memory, etc. An obvious downside is that this std::vector
is now distinct from a regular std::vector
, since it uses a custom allocator.
Polymorphic Allocators
If you want even more customization, such as using a totally different type of allocator in the same vector type, this becomes annoying.
It's also annoying that std::vector<T>
and std::vector<T, mmap_allocator<T>>
are incompatible.
To solve this, there are polymorphic allocators:
struct mmap_resource : std::pmr::memory_resource { /* ... */ };
mmap_resource create_mmap_resource(std::string_view file) {
/* ... */
}
auto use_vec() {
// TODO: the allocator doesn't own the memory resource, so
// we might need to bundle the vector and the resource in
// a struct, etc.
auto resource = create_mmap_resource(...);
std::pmr::polymorphic_allocator alloc = &resource;
std::pmr::vector<data> result(alloc);
/* ... */
}
Polymorphic allocators are wrappers for a polymorphic class std::pmr::memory_resource
, which you can customize.
Also see: polymorphic_allocator: when and why should I use it?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论