【发布时间】:2009-10-21 23:21:59
【问题描述】:
我想使用 STL 自定义分配器类的不同实例来管理不同的内存空间,然后能够为 STL 容器指定一个分配器实例,以便每个容器仅从其分配的内存空间中提取。但我不明白我怎么能做到这一点。我看到了如何将分配器类型传递给 STL 容器的模板参数,但我想要类似于将分配器实例传递给 STL 容器的构造函数的东西。有没有办法在 STL 中做到这一点?
【问题讨论】:
标签: c++ stl memory-management
我想使用 STL 自定义分配器类的不同实例来管理不同的内存空间,然后能够为 STL 容器指定一个分配器实例,以便每个容器仅从其分配的内存空间中提取。但我不明白我怎么能做到这一点。我看到了如何将分配器类型传递给 STL 容器的模板参数,但我想要类似于将分配器实例传递给 STL 容器的构造函数的东西。有没有办法在 STL 中做到这一点?
【问题讨论】:
标签: c++ stl memory-management
不幸的是,STL 分配器不能有状态(或者至少必须非常小心如何使用该状态)——特定分配器类型的每个实例都必须等效,STL 容器才能有效地使用它们。我现在不记得细节,但我知道 Scott Meyers 在"Effective STL",第 10 项:注意分配器约定和限制中详细讨论了这个问题。
但是,您可以拥有与封装在分配器类型中的分配器之间的差异非常相似的模板化分配器,并使用分配器模板的不同“实例化”(每个模板“实例化”是不同的类型)。同样,我记得 Meyers 非常清楚地讨论了这一点。
例如从Anthony Aue, "Improving Performance with Custom Pool Allocators for STL"的一篇文章中看到这一段:
一个可能更严重的警告是,由于分配器使用非静态数据,它在技术上不符合标准,因为标准要求相同类型的分配器是等效的。有关该问题的详细说明,请参阅有效 STL(第 10 项)。这相当于要求给定类型的分配器能够释放由该类型的分配器的任何其他实例分配的内存。对于标准容器的许多用途,这个要求是不必要的(有些人可能会说是严苛的)。但是,在两种情况下这个要求是绝对必要的:list::splice 和 swap()。 swap() 的情况特别严重,因为需要它以异常安全的方式在容器上实现某些操作(参见异常 C++,第 12 条)。从技术上讲,可以(并且在某些情况下,是)在面对不相等比较的分配器时实现交换——可以复制项目或者可以将分配器与数据一起交换——但情况并非总是如此。出于这个原因,如果你使用 swap() 或 list::splice,你应该确保使用 HoldingPolicySingleton;否则,你一定会遇到一些非常讨厌的行为。
另请参阅 Stephan T. Lavavej 在this newsgroup thread 中的讨论。
如果其他人在此期间不提供详细信息,我会在今晚晚些时候更新。
【讨论】:
STL 容器允许您将分配器作为参数传递给构造函数。
例如,这里是向量的适当构造函数:
explicit vector(const Allocator& = Allocator());
explicit vector(size_type n, const T& value = T(),
const Allocator& = Allocator());
template <class InputIterator>
vector(InputIterator first, InputIterator last,
const Allocator& = Allocator());
默认情况下,它们只使用默认构造的分配器。
【讨论】:
也许您可以编写一组分配器类型,其中包含指向单独内存空间的静态指针。
然后,当 STL 容器构造其分配器时,分配器使用分配给该分配器的内存空间。
为简单起见,假设您要使用两个内存空间。创建两种分配器类型,每个空间一种。根据需要将分配器类型传递给 STL 容器构造函数。
【讨论】: