Предположим, что я хочу построить векторный контейнер, который unlike std::vector, позволяет неинициализированное хранилище. Использование контейнера, скажем vec <T>
, будет примерно так:создание вектора для разрешения неинициализированного хранилища
Пользователь явно указывается вектор должен выделить N неинициализированным элементы так:
vec <T> a(N, no_init);
В какой-то момент, когда данные известны, пользователь явно инициализирует элемент в позиции
n
с использованием аргументовargs...
:a.init(n, args...);
или, что эквивалентно, создает элемент вручную:
new (&a[n]) T(args...);
Другие операции могут инициализировать или копировать более широком масштабе (как
std::uninitialized_copy
), но это только для удобства; основная базовая операция такая же.После выполнения некоторой задачи вектор может быть оставлен с инициализированными элементами, а другие нет. Вектор не содержит никакой дополнительной информации, поэтому, прежде чем освободить память, он либо уничтожит все элементы в любом случае, либо уничтожит только в зависимости от
T
.
Я уверен, что это можно сделать, только я не уверен в последствиях. Естественно, мы хотели бы, чтобы эта структура была безопасной для всех типов T
, предполагая, что пользователь не пытается использовать неинициализированный элемент перед его созданием. Это может звучать как сильное предположение, но доступ к элементам только внутри диапазона вектора не так уж отличается от предположения, и это так распространено.
Так что мои вопросы:
Для каких типов было бы безопасно разрешить такую неинициализированную работу как в
vec <T> a(no_init)
? Думаю,is_pod
будет в порядке и, скорее всего,is_trivial
. Я бы не хотел ставить больше ограничений, чем необходимо.Должно ли уничтожение выполняться всегда или только для некоторых типов? Было бы так же ограничение, как указано выше? Как насчет
is_trivially_destructible
? Идея состоит в том, что разрушение элемента, имеющего , не, или наоборот (не, разрушающий построенный элемент) не должно нанести вреда.Есть ли главный недостаток в этой попытке, за исключением очевидного риска привлечения большей ответственности перед пользователем?
Все дело в том, что, когда пользователь действительно нуждается в такой функциональности для выполнения, решения более низкого уровня, как std::get_temporary_buffer
или ручного распределения (например, с operator new()
) может быть более рискованным с точки зрения утечки. Я знаю о std::vector::emplace_back()
, но это действительно не то же самое.
Вы хотите создать контейнер, который будет действовать как 'std :: vector' после того, как вы выберете' reserve'? Из [this ref] (http://www.cplusplus.com/reference/vector/vector/reserve/): «Требует, чтобы векторная емкость была по крайней мере достаточной, чтобы содержать n элементов». , –
Похоже, что это не тот вектор, который вы хотите вообще. Что случилось с ассоциативным контейнером? –
@ wesley.mesquita Только частично. Да, я хочу, чтобы распределение было «зарезервировано», но я также хочу, чтобы данные были полностью доступны. Например. 'size()' должен включать эти выделенные элементы. – iavr