2010-03-24 3 views
19

Я пытаюсь написать класс контейнера, который использует STL-распределители. То, что я в настоящее время сделать это иметь частный членКак использовать std :: allocator в моем собственном классе контейнера

std::allocator<T> alloc_; 

(это будет позже шаблонным, так что пользователь может выбрать другой аллокатор), а затем вызвать

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

, чтобы получить указатель на вновь выделенный объект 'T' (и использовать alloc_.construct для вызова конструктора, см. ответ ниже). Это работает с библиотекой GNU C++.

Однако, при использовании STLPort на Solaris это не позволяет делать правильные вещи и ведет к различным видам ошибок коррупции в памяти. Если я вместо этого сделаю

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

затем все работает как следует.

Каков правильный способ использования stl :: allocator? Версия STLPort/Solaris не скомпилирована с g ++, но правильно ли g ++?

+7

В стандартной библиотеке ничего не называется 'allocator_interface'. – AraK

ответ

8

Что-то, что вы, возможно, захотите сделать, это иметь собственный пользовательский номер allocator, который вы можете использовать, чтобы увидеть, как стандартные контейнеры взаимодействуют с распределителями. Стефан Т. Лававей написал красивый, простой, который называется mallocator. Бросьте его в тестовую программу, которая использует различные STL контейнеры и вы можете легко увидеть, как распределителем используется стандартными контейнерами:

Не все функции интерфейса в mallocator (например как construct() и destroy()) используются выходные данные трассировки, поэтому вам может потребоваться отбросить инструкции трассировки, чтобы более легко увидеть, как стандартные контейнеры могут использовать эти функции, не прибегая к отладчику.

Это должно дать вам представление о том, как можно использовать ваши контейнеры для использования таможни allocator.

+0

К сожалению, он не отслеживает «конструкцию», которая является функцией, которую он не использовал: -/ –

+0

Это правда (я упомянул об этом недостатке в своем ответе), и я намеревался, чтобы мой ответ был более или менее боковой панелью к вашему ответу, который указывает на проблему напрямую. Lavavej разместил «mallocator» в качестве простого примера пользовательского распределителя. Я предлагал, чтобы его также можно было использовать как простой способ получить представление о том, как контейнеры используют распределители, но возможно, что для улучшения трассировки для этой цели могут потребоваться некоторые незначительные изменения. –

16

Вам необходимо выделить и построить с помощью распределителя. Что-то вроде этого:

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

Много вещей прямо нарушены, если вы не начинаете с правильно построенного объекта. Представьте, что std::string выделяется, но не сконструирован. Когда вы попытаетесь назначить ему, сначала попробуйте очистить свое старое содержимое, освободив некоторые данные, что, конечно же, будет значением мусора из кучи и сбоя.

+0

Да, я знаю, я действительно это сделал, хотя я использовал вместо размещения std :: allocator :: construct (что, вероятно, не рекомендуется, поэтому я изменил это сейчас). Однако выясняется, что STLPort 4.x не знает о std :: allocator :: construct либо ... –

+0

Если у STLPort нет 'std :: allocator :: construct', то он сломан, не беспокойтесь, даже используя его. Я могу вам точно сказать, что 5.1.5 (версия, которую я установил, имеет ее и отлично работает). –

+1

Я смотрел, чтобы удовлетворить мое любопытство, STLPort 4.x ** имеет ** соответствующий стандарт соответствия 'std :: allocator'. В 4.6 функция 'construct' находится в строке 365' stlport/stl/_alloc.h'.Если он не работает, ваша установка неверна. –

Смежные вопросы