如何在自己的容器类中使用std::allocator

22

我正在尝试编写一个使用STL分配器的容器类。目前我的做法是拥有一个私有成员

std::allocator<T> alloc_;

(稍后将进行模板化,以便用户可以选择不同的分配器),然后调用

T* ptr = alloc_.allocate(1,0);

要获取指向新分配的'T'对象的指针(并使用alloc_.construct调用构造函数;请参见下面的答案)。这适用于GNU C++库。

然而,在Solaris上使用STLPort时,这样做会导致无法正确执行,并导致各种奇怪的内存损坏错误。如果我改为

std::allocator_interface<std::allocator<T> > alloc_;

如果一切正常,那么它就是按预期工作的。

如何正确使用stl::allocator?STLPort / Solaris版本在g ++下无法编译,但g ++是正确的吗?


7
标准库中不存在名为allocator_interface的东西。 - Khaled Alshaya
2个回答

16
您需要同时使用分配器进行内存分配和构造。可以像这样进行操作:

T* ptr = alloc_.allocate(1,0);
alloc_.construct(ptr, value);

如果你不从一个正确构造的对象开始,很多东西都会彻底破裂。想象一下分配了但未构造的std::string。当你尝试对它进行赋值时,它将首先尝试通过释放一些数据来清理其旧内容,这些数据当然来自堆上的垃圾值,会导致程序崩溃。

是的,我知道,我实际上已经这样做了,不过我使用了placement new而不是std::allocator<T>::construct(这可能不可取,所以我现在已经改变了)。然而,事实证明STLPort 4.x也不知道std::allocator<T>::construct... - Kasper Peeters
如果STLPort没有std::allocator<T>::construct,那么它是有问题的,甚至不要使用它。我可以确定地告诉你,5.1.5版本(我安装的版本)有这个函数并且可以正常工作。 - Evan Teran
1
我满怀好奇地查看了一下,STLPort 4.x确实拥有一个符合标准的std::allocator。在4.6版本中,construct函数位于stlport/stl/_alloc.h的第365行。如果它不能正常工作,那么你的安装可能存在问题。 - Evan Teran
1
在C++ 20中,construct已被弃用。 - KRoy

10
你可能想做的一件事是拥有自己定制的分配器(allocator),以便了解标准容器与分配器的交互方式。Stephan T. Lavavej发布了一个很好、简单的分配器,叫做"mallocator"。将它放入一个使用各种STL容器的测试程序中,你就可以轻松地看到标准容器如何使用这个分配器。 并非所有的接口函数在mallocator中都被插入了跟踪输出,因此您可能希望在其中添加跟踪语句,以更容易地查看标准容器如何使用这些函数而无需使用调试器。
这样应该能让您很好地了解您的容器可能如何使用自定义的allocator

不幸的是,它无法跟踪 construct,这是他未能使用的函数 :-/ - Evan Teran
这是真的(我在我的答案中提到了这个缺点),而且我原本打算我的答案更多地是一个旁注,直接指出问题。Lavavej发布了mallocator作为自定义分配器的一个简单示例。我建议它也可以用作一种轻松获取容器使用分配器方式的方法,但可能需要进行一些微小修改以改进跟踪功能。 - Michael Burr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接