Я реализую тип контейнера, которому принадлежит некоторая память, которую я создаю, используя std::make_unique_for_overwrite()
. Учитывая, что эта функция специально возвращает std::unique_ptr
в неинициализированную память, я хотел использовать алгоритмы неинициализированной памяти, предусмотренные стандартом. Я заметил, что этих функций нет constexpr
, только когда пытался написать тесты с использованием static_assert
для моего контейнера, только чтобы понять, что мои constexpr
конструкторы не такие constexpr
в конце концов из-за моих вызовов std::ranges::uninitialized_copy()
.
Мой вопрос: в чем именно разница между std::ranges::copy()
и его неинициализированным братом std::ranges::uninitialized_copy()
, и существует ли достаточно значительная разница в производительности, чтобы отказаться от совместимости constexpr
?
@康桓瑋 я не спрашиваю, почему это не так constexpr
, я спрашиваю, есть ли достаточно значительная разница между этими двумя алгоритмами, чтобы предпочитать использовать один вместо другого
Вероятно, не....
@SHIPWECK Тогда stackoverflow.com/questions/67992613/…?
make_unique_for_overwrite
и make_shared_for_overwrite
обычно следует использовать с тривиальным типом. Я не понимаю логики, лежащей в основе не ограничивать их этими типами. Для других типов они просто создают объекты по умолчанию. Для тривиальных типов конструктор присваивания и копирования функционально эквивалентен. uninitialized_copy
обычно предназначен для управления памятью C, где выделение и построение объектов временно не связаны. Я бы предпочел определить распределитель костюмов и вместо этого создать вектор.
Учитывая, что эта функция специально возвращает
std::unique_ptr
в неинициализированную память.
Это не так. Это unique_ptr
для объекта, инициализированного по умолчанию (или массива, или объектов). Это не неинициализация: использование алгоритмов uninitialized_*
создаст новый объект поверх существующего объекта, что может привести к утечке памяти, если деструктор пропущен.
«Преимущество производительности» этих алгоритмов заключается в том, что альтернативой обычно является конструкция по умолчанию, а затем использование оператора присваивания. Это действительно преимущество «корректности», поскольку вы не можете ожидать, что универсальные объекты будут конструируемыми по умолчанию, но в качестве побочного эффекта вы избегаете (возможно, дорогостоящего) конструктора по умолчанию.
И когда у вас есть два выбора между «constexpr
-дружественным» алгоритмом и более производительным алгоритмом, используйте if consteval
и используйте оба.
О, спасибо! Тогда в чем разница между std::make_unique
и std::make_unique_for_overwrite
? Если я не предоставлю аргументов std::make_unique
, создаст ли он по умолчанию объект/массив, на который указывает?
@SHIPWECK В принципе, для классов это не имеет значения. Разница между make_unique<int[100]>()
и make_unique_for_overwrite<int[]>(100)
заключается в том, что первый инициализируется 100 нулями, а второй инициализируется по умолчанию (т. е. недействителен для чтения, действителен для записи).
Возможно, дубликат stackoverflow.com/questions/66030088/…