Как использовать std:: allocator в моем собственном классе контейнера
Я пытаюсь написать класс контейнера, который использует STL-распределители. То, что я сейчас делаю, это иметь частного участника
std::allocator<T> alloc_;
(это позже будет шаблоном, чтобы пользователь мог выбрать другой распределитель), а затем вызовите
T* ptr = alloc_.allocate(1,0);
чтобы получить указатель на вновь выделенный объект 'T' (и использовать alloc_.construct для вызова конструктора, см. ответ ниже). Это работает с библиотекой GNU С++.
Однако, с STLPort на Solaris, это не позволяет делать правильные вещи и приводит к различным видам ошибок коррупции памяти. Если я вместо этого делаю
std::allocator_interface<std::allocator<T> > alloc_;
тогда все работает так, как должно.
Каков правильный способ использования stl:: allocator? Версия STLPort/Solaris не скомпилирована с g++, но правильно ли g++?
Ответы
Ответ 1
Что-то, что вы, возможно, захотите сделать, это иметь собственный пользовательский allocator
, который вы можете использовать, чтобы увидеть, как стандартные контейнеры взаимодействуют с распределителями. Стефан Т. Лававей написал красивый, простой, названный mallocator
. Бросьте его в тестовую программу, в которой используются различные контейнеры STL, и вы можете легко увидеть, как распределитель используется стандартными контейнерами:
Не все функции интерфейса в mallocator
(например, construct()
и destroy()
) используются для вывода трассировки, поэтому вам может потребоваться отбросить инструкции трассировки, чтобы более легко увидеть, как могут использоваться стандартные контейнеры используйте эти функции, не прибегая к отладчику.
Это должно дать вам представление о том, как можно ожидать, что ваши контейнеры будут использовать пользовательский allocator
.
Ответ 2
Вам нужно как распределить, так и построить с помощью распределителя. Что-то вроде этого:
T* ptr = alloc_.allocate(1,0);
alloc_.construct(ptr, value);
Множество вещей прямо нарушается, если вы не начинаете с правильно построенного объекта. Представьте, что std::string
выделено, но не сконструировано. Когда вы попытаетесь назначить ему, сначала попробуйте очистить свое старое содержимое, освободив некоторые данные, что, конечно же, будет значением мусора из кучи и сбоя.