2009-03-17 6 views
7

Для моего проекта я пишу некоторые контейнеры STL с нуля (у меня есть причины). Поскольку я имитирую функциональность и интерфейсы STL так близко, я прилагаю все усилия, чтобы придерживаться политики «если она имеет то же имя, что и стандартная конструкция, она будет соответствовать стандарту как можно больше».std :: allocator construct/destroy vs. placement new/p-> ~ T()

Итак, конечно, мои контейнеры принимают распределители как параметр шаблона, что очень приятно, так как оно позволяет использовать некоторые схемы пользовательского распределения. На мой вопрос.

Интерфейс std::allocator отделяет выделение памяти от конструкции объекта. Также он отделяет освобождение от разрушения. Это имеет смысл с тех пор, как вы получаете память из более или менее неуместного для правильного построения объекта в C++.

Таким образом, есть две строительные/отмена функции, которые выглядят, как это для реализации по умолчанию (поднятой прямо из книги):

void construct(pointer p, const T& val) { new(p) T(val); } 
void destroy(pointer p)     { p->~T(); } 

, как вы можете видеть, построить просто вызывает размещение нового и уничтожить просто вызывает деструктор ,

Есть ли причина использовать их только с использованием синтаксиса размещения нового и деструктора? может ли «правильный» распределитель реализовать их по-другому? Или я уверен, что все реализации распределителей, которые соответствуют стандарту, будут иметь методы построения/уничтожения, реализованные таким образом?

Более конкретно, можно ли сказать, что я всегда могу использовать std::uninitialized_copy и std::uninitialized_fill для конструирования элементов моих контейнеров?

Спасибо.

ответ

8

Распределитель может добавлять отчеты о регистрации до и после строительства/уничтожения или любые другие побочные эффекты, о которых он мог бы подумать.

Конечно фактическое строительство должно происходить путем вызова размещения новых и деструктор, но в своде правил он не говорит, что ничего другого не должно произойти в конструкции/уничтожить ФУНКЦИИ

+1

да, это хороший момент, это может быть хорошим крюком для ведения журнала «после распределения/предварительной сборки» или отслеживания memleak. –

+1

Этот ответ правильный, но немного вводит в заблуждение. Побочные эффекты, такие как ведение журнала, на самом деле довольно сложно сделать с правильной безопасностью исключений. Чаще всего настройка настраивается на встроенное новое выражение, например. аргументы конструктора. См. Https://groups.google.com/a/isocpp.org/d/topic/std-discussion/yZLnYy_y2z0/discussion – Potatoswatter

2

Это просто, чтобы скрыть детали распределения в методе. то есть мы предоставляем API для строительства и разрушения, в будущем мы сможем изменить реализацию. Теперь мы используем новое размещение для выделения памяти, в будущем, если мы хотим изменить распределение, нам просто нужно изменить эти два метода.

+0

да, я согласен с этим. Но мне любопытно, может ли стандарт изменить их? (особенно с пользовательскими распределителями, нам не нужно ждать нового std для ...). –

+0

'allocator :: construct' не имеет ничего общего с распределением, и поскольку все распределители (теперь) распределяются, я не могу себе представить, почему они заставили бы' construct' делать что-нибудь еще –

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