std::ranges::uninitialized_fill_n
| Определено в заголовочном файле <memory>
|
||
| Сигнатура вызова |
||
template< прямой-диапазон-без-исключения I, class T > requires std::constructible_from<std::iter_value_t<I>, const T&> I uninitialized_fill_n( I first, std::iter_difference_t<I> n, const T& x ); |
(начиная с C++20) | |
Создаёт n копий заданного значения x в неинициализированной области памяти, обозначенной диапазоном [first, first + n), как если бы
for (; n--; ++first)
{
::new (static_cast<void*>(std::addressof(*first)))
std::remove_reference_t<std::iter_reference_t<I>>(x);
}
Если во время инициализации генерируется исключение, уже созданные объекты уничтожаются в неопределённом порядке.
Функционально-подобные объекты, описанные на этой странице, являются ниблоидами, то есть:
- Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
- Ни один из них не виден для поиска, зависящего от аргумента.
- Когда какой-либо из них обнаруживается обычным неквалифицированным поиском по имени слева от оператора вызова функции, поиск, зависящий от аргумента запрещён.
На практике они могут быть реализованы как функциональные объекты или со специальными расширениями компилятора.
Параметры
| first | — | начало диапазона элементов для инициализации |
| n | — | количество элементов для создания |
| x | — | значение, с которым создавать элементы |
Возвращаемое значение
Итератор, равный first + n.
Сложность
Линейная по n.
Исключения
Исключение, генерируемые при создании элементов в целевом диапазоне, если таковые имеются.
Примечание
Реализация может повысить эффективность ranges::uninitialized_fill_n, например, используя ranges::fill_n, если тип значения выходного диапазона является TrivialType.
Возможная реализация
struct uninitialized_fill_n_fn
{
template<прямой-диапазон-без-исключения I, class T>
requires std::constructible_from<std::iter_value_t<I>, const T&>
I operator()(I first, std::iter_difference_t<I> n, const T& x) const
{
I rollback{first};
try
{
for (; n-- > 0; ++first)
ranges::construct_at(std::addressof(*first), x);
return first;
}
catch (...) // откат: уничтожить созданные элементы
{
for (; rollback != first; ++rollback)
ranges::destroy_at(std::addressof(*rollback));
throw;
}
}
};
inline constexpr uninitialized_fill_n_fn uninitialized_fill_n{};
|
Пример
#include <iostream>
#include <memory>
#include <string>
int main()
{
constexpr int n{3};
alignas(alignof(std::string)) char out[n * sizeof(std::string)];
try
{
auto first{reinterpret_cast<std::string*>(out)};
auto last = std::ranges::uninitialized_fill_n(first, n, "cppreference");
for (auto it{first}; it != last; ++it)
std::cout << *it << '\n';
std::ranges::destroy(first, last);
}
catch (...)
{
std::cout << "Исключение!\n";
}
}
Вывод:
cppreference
cppreference
cppreference
Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| LWG 3870 | C++20 | этот алгоритм может создавать объекты в const хранилище
|
запрещено |
Смотрите также
(C++20) |
копирует объект в неинициализированную область памяти, определяемую диапазоном (ниблоид) |
| копирует объект в неинициализированную область памяти, определяемую началом и количеством (шаблон функции) |