std::uninitialized_default_construct_n
Материал из cppreference.com
Определено в заголовочном файле <memory> | ||
template<class ForwardIt, class Size > ForwardIt uninitialized_default_construct_n( ForwardIt first, Size n ); | (1) | (начиная с C++17) |
template<class ExecutionPolicy, class ForwardIt, class Size > ForwardIt uninitialized_default_construct_n( ExecutionPolicy&& policy, | (2) | (начиная с C++17) |
1) Создаёт n объектов типа typenamestd::iterator_traits<ForwardIt>::value_type в неинициализированном хранилище, начиная с firstинициализацией по умолчанию, как если бы for(; n >0;(void)++first, --n)
::new(static_cast<void*>(std::addressof(*first)))
typenamestd::iterator_traits<ForwardIt>::value_type;
::new(static_cast<void*>(std::addressof(*first)))
typenamestd::iterator_traits<ForwardIt>::value_type;
Если во время инициализации возникает исключение, уже созданные объекты уничтожаются в неопределённом порядке.
2) То же, что и (1), но выполняется в соответствии с policy. Эта перегрузка не участвует в разрешении перегрузки, если только
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> не равно true. | (до C++20) |
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> не равно true. | (начиная с C++20) |
Содержание |
[править]Параметры
first | — | начало диапазона элементов для инициализации |
n | — | количество элементов для создания |
policy | — | используемая политика выполнения. Подробнее смотрите политика выполнения. |
Требования к типам | ||
-ForwardIt должен соответствовать требованиям LegacyForwardIterator. | ||
-Никакое инкрементирование, присваивание, сравнение или косвенное обращение через действительные экземпляры ForwardIt не могут вызывать исключения. |
[править]Возвращаемое значение
Конец диапазона объектов (т.е. std::next(first, n)).
[править]Сложность
Линейная по n.
[править]Исключения
Перегрузка с параметром шаблона по имени ExecutionPolicy
сообщает об ошибках следующим образом:
- Если выполнение функции, вызванной как часть алгоритма, вызывает исключение и
ExecutionPolicy
является одной из стандартных политик, вызывается std::terminate. Для любой другойExecutionPolicy
поведение определяется реализацией. - Если алгоритму не удаётся выделить память, генерируется std::bad_alloc.
[править]Возможная реализация
template<class ForwardIt, class Size> ForwardIt uninitialized_default_construct_n(ForwardIt first, Size n){using T =typenamestd::iterator_traits<ForwardIt>::value_type; ForwardIt current = first; try{for(; n >0;(void)++current, --n)::new(const_cast<void*>(static_cast<constvolatilevoid*>(std::addressof(*current)))) T;return current;}catch(...){std::destroy(first, current);throw;}} |
[править]Пример
Запустить этот код
#include <cstring>#include <iostream>#include <memory>#include <string> int main(){struct S {std::string m{"значение по умолчанию"};}; constexprint n{3}; alignas(alignof(S))unsignedchar mem[n * sizeof(S)]; try{auto first{reinterpret_cast<S*>(mem)};auto last = std::uninitialized_default_construct_n(first, n); for(auto it{first}; it != last;++it)std::cout<< it->m <<'\n'; std::destroy(first, last);}catch(...){std::cout<<"Исключение!\n";} // Обратите внимание, что для "тривиальных типов" uninitialized_default_construct_n// обычно не инициализирует нулями данную неинициализированную область памяти.int v[]{1, 2, 3, 4};constint original[]{1, 2, 3, 4}; std::uninitialized_default_construct_n(std::begin(v), std::size(v)); // Попытка доступа к v может иметь неопределённое поведение вплоть до CWG 1997:// for (const int i : v)// std::cout << i << ' '; // Результат не указан:std::cout<<(std::memcmp(v, original, sizeof(v))==0?"не":"")<<"модифицированный\n";}
Возможный вывод:
значение по умолчанию значение по умолчанию значение по умолчанию модифицированный
[править]Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 3870 | C++20 | этот алгоритм может создавать объекты в const хранилище | запрещено |
[править]Смотрите также
создаёт объекты инициализацией по умолчанию в неинициализированной области памяти, определяемой диапазоном (шаблон функции) | |
создаёт объекты инициализацией значением в неинициализированной области памяти, определяемой началом и количеством (шаблон функции) | |
создаёт объекты инициализацией по умолчанию в неинициализированной области памяти, определяемой началом и количеством (ниблоид) |