Дополнительно
Есть ли польза от unique_ptr с массивом?
В std::unique_ptr
есть поддержка массивов, например:
std::unique_ptr<int[]> p(new int[10]);
но нужна ли она? Возможно, удобнее использовать std::vector
или std::array
.
Находите ли вы применение этой конструкции?
219
16
Некоторые люди не могут позволить себе использовать
std::vector
, даже с аллокаторами. Некоторым нужен динамически изменяемый размер массива, поэтомуstd::array
не подходит. А некоторые люди получают свои массивы из другого кода, который, как известно, возвращает массив; и этот код не будет переписан для возвратаvector
или чего-то подобного.Разрешая
unique_ptr
, вы удовлетворяете эти потребности.Короче говоря, вы используете
unique_ptr
, когда вам это нужно. Когда альтернативные варианты просто не подходят. Это инструмент последнего средства.Есть компромиссные варианты, а вы выбираете решение, которое соответствует тому, что вы хотите. С верхней части моей головы:
Начальный размер
вектор
иunique_ptr не<Т[]>
чтобы размер будет определен во время выполнениямассив
только позволяет размер будет определен во время компиляцииИзменение размера
время
иunique_ptr не<Т[]>
не допустить изменения размераХранение
вектор
иunique_ptr не<Т[]>
хранить данные за пределами объекта (обычно в куче)массив
хранит данные непосредственно в объектеКопирование
массив
ивектор
разрешить копированиеЗамена/перемещение
вектор
иunique_ptr не<Т[]>
за O(1) временисвоп
и ход операциимассива
имеет сложность o(n) временисвоп
и ход операций, где n-количество элементов в массивеУказатель/ссылку/итератор недействительным
массив
обеспечивает указатели, ссылки и итераторы никогда не будут аннулированы, пока объект жив, даже насвоп()
unique_ptr не<Т[]>
не имеет итераторы; указатели и ссылки являются лишь законной силысвоп()
пока объект жив. (После замены, указатели точку в массив, который вы заменили, так они'вновь еще "не действует" в этом смысле.)Совместимость с понятий и алгоритмов
время
ивектор
оба контейнерыunique_ptr не<Т[]>
это не контейнерЯ должен признать, это выглядит как возможность для небольшого рефакторинга с учетом политики дизайна.
Одна из причин, вы могли бы использовать `unique_ptr не является если вы Don'т хотите оплатить стоимость выполнения значение-инициализация массива.
В СТД::вектор
конструктор
СТД::вектор::размер () будет значение-инициализироватьт
- но "новые" не будут этого делать, еслиТ
представляет собой стручок.См https://stackoverflow.com/questions/15097783/value-initialized-objects-in-c11-and-stdvector-constructor
Обратите внимание, что `вектор::заповедник-это не альтернатива здесь: https://stackoverflow.com/questions/8228072/is-accessing-the-raw-pointer-after-stdvectorreserve-safe
Это'с той же причине C программист может выбрать функция
malloc
запамятью
.Вектор
std::vector
можно копировать, аunique_ptr
позволяет выразить уникальное владение массивом. С другой стороны,std::array
требует определения размера во время компиляции, что может быть невозможно в некоторых ситуациях.Скотт Мейерс рассказывает в эффективный современный c++
Я думаю, что Чарльз сальвии'ы ответьте хотя актуален:, что
с std::unique_ptr не<Т[]>
это единственный способ, чтобы инициализировать пустой массив, чей размер не известен во время компиляции. Что бы Скотт Мейерс нужно сказать о такой мотивации, используяс std::unique_ptr не<Т[]>
?Вопреки СТД::вектор
и
с std::массив,
с std::unique_ptr не может иметь нулевой указатель. Это пригодится при работе с API-интерфейсы c, ожидающие или массив или null:Я использовал
unique_ptr
для реализации пулов предварительно распределенной памяти, используемых в игровом движке. Идея заключается в том, чтобы предоставить предварительно распределенные пулы памяти, используемые вместо динамического распределения для возврата результатов запросов столкновений и других вещей, таких как физика частиц, без необходимости выделять / освобождать память в каждом кадре. Это довольно удобно для такого рода сценариев, где вам нужны пулы памяти для размещения объектов с ограниченным временем жизни (обычно один, 2 или 3 кадра), которые не требуют логики уничтожения (только деаллокация памяти).В двух словах: это'ы на сегодняшний день наиболее эффективный для памяти.
В СТД::строка
поставляется с указателем, длинну, и на "короткие строки-оптимизация и" буфера. Но моя ситуация мне нужно сохранить строку, которая почти всегда пустая, в структуру, которая у меня сотни тысяч. В C, я бы просто использовать
charи, и было бы нуль большую часть времени. Который работает для C++, тоже, за исключением того, что
charи не имеет деструктора, а не'т знаем, чтобы удалить себя. Напротив,
с std::unique_ptr не<символ[]>будет удалить себя, когда он выходит из области видимости. Пустой
СТД::строказанимает 32 байта, но пустой
с std::unique_ptr не<символ[]>` занимает 8 байт, то есть ровно на размер указателя.Самый большой недостаток в том, что каждый раз, когда я хочу знать длину строки, Мне нужно позвонить
функция strlen
на нем.Общий шаблон может быть найден в [некоторых][GetPackageApplicationIds_MSDN] ОС Windows API-интерфейса Win32 звонки, в которых использование
с std::unique_ptr не<Т[]>
может пригодиться, например, когда вы Don'т знаю, насколько большой буфер вывода должен быть при вызове некоторые Win32 API (так что буду писать некоторые данные в буфер):[GetPackageApplicationIds_MSDN]: http://msdn.microsoft.com/en-us/library/windows/desktop/dn270603(В=и 85).аспн
Я столкнулся с такой случай, когда я должен был использовать
с std::unique_ptr не<типа bool [] и GT;
, который был в HDF5 библиотека (библиотека для эффективное бинарное хранение данных, используемый много в науке). Некоторые компиляторы (в Visual Studio 2015 в моем случае) обеспечивают сжатиеСТД::вектор<типа bool и GT;
(с помощью 8 значений в каждый байт), что является катастрофой для что-то вроде HDF5, который не'т волнует, что сжатие. С СТД::вектор<типа bool и GT;`, HDF5 был в конце концов читать мусор из-за этого сжатия.Угадайте, кто был там для спасения, в случае, когда СТД::вектор` ничего't работа, и мне нужно выделить динамический массив чисто? :-)
Еще одна причина, чтобы разрешить и использовать с std::unique_ptr не<Т [] и GT;`, что еще'т было упомянуто в ответах до сих пор: она позволяет вперед-объявить тип элемента массива.
Это полезно, когда вы хотите минимизировать прикованный
#включить
высказывания в заголовках (оптимизировать производительность построения.)Например
С помощью данной структуры кода, кто может
#включить и"класса MyClass.ч"
В и использоватькласса MyClass
, без включения внутренних зависимостей, необходимых для осуществлениякласса MyClass::m_InternalArray
.Если m_InternalArray
был объявлен как
с std::массив, или
СТД::вектор<...>`, соответственно - результат был бы покушение на использование неполного типа, что ошибка времени компиляции.Чтобы ответить на людей, думая, что вы "не надо" и использовать
вектор
вместоunique_ptr не
у меня есть дело в программирования CUDA на GPU при выделении памяти в устройство необходимо зайти на массив указателей (с cudaMalloc). Затем, при получении этих данных в хост, нужно идти снова на указатель и
unique_ptr неэто хорошо, чтобы легко справиться указатель. Дополнительных затрат на преобразование двойных*
ввектор<двойной>
является ненужным и приводит к потере производительности.СТД::вектор
, например, для предотвращения неосторожного программиста от случайного представляем копииЕсть общее правило, что c++ контейнеры должны быть предпочтительнее, чем прокатки свой собственный с указателями. Это общее правило, которое не имеет исключений. Там's больше, это лишь примеры.
Они могут быть верным ответ можно получить только ткнуть указателем через существующий API (думаю окне сообщений или потоков, связанных с обратного вызова, параметры), которые имеют определенную продолжительность жизни после того, как "поймали" на другую сторону люка, но который никакого отношения к вызывающему коду:
Мы все хотим, чтобы все было хорошо для нас. C++ - это для другого раза.
unique_ptr не<символ[]>
может быть использована там, где требуется производительность и удобство работы с C++. Считаю нужно работать на миллионы (если не миллиарды, если вы Don'т доверять еще) строк. Хранение каждого из них в отдельную строку или вектор<чар>` объект станет катастрофой для памяти (кучи) режимы управления. Особенно, если вам нужно выделить и удалить разные строки много раз.Тем не менее, можно выделить один буфер для хранения, что много строк. Вы бы'т, как
типа char* буфер = (тип char*)Танос(total_size);
по понятным причинам (если не очевидно, поиск по "Почему использовать смарт-ПТРС-то"). Вы бы какunique_ptr не<типа char[]> буфер(новая Чаре[total_size]);
По аналогии, такую же производительность&соображения удобства применяется для данных типа char`(считают миллионы векторов/матриц/объекты).
Если вам нужен динамический массив объектов, которые не копируют-конструктивны, то умный указатель на массив является способом пойти. Например, что если вам нужен массив атомной и Л;int>В С.