std::ranges::uninitialized_fill_n
Определено в заголовке <memory> |
||
|---|---|---|
| Подпись вызова | ||
template< no-throw-forward-range 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);
}Если во время инициализации возникает исключение, объекты, которые уже были созданы, уничтожаются в неопределенном порядке.
Функциональные сущности, описанные на этой странице, являются niebloids, то есть:
- Явные списки шаблонов аргументов не могут быть указаны при вызове ни одного из них.
- Ни один из них не виден для поиска зависимых от аргументов.
- Когда любой из них найден обычным поиском без квалификаторов в качестве имени слева от оператора вызова функции, поиск зависимых от аргументов ингибируется.
На практике они могут быть реализованы как объекты функций или с помощью специальных расширений компилятора.
Параметры
| first | - | начало диапазона элементов для инициализации |
| n | - | количество элементов для создания |
| x | - | значение для создания элементов |
Возвращаемое значение
Итератор, равный first + n.
Сложность
Линейна по отношению к n.
Исключения
Исключение, сгенерированное при создании элементов в целевом диапазоне, если таковое имеется.
Примечания
Реализация может улучшить эффективность ranges::uninitialized_fill_n, например, используя ranges::fill_n, если тип значения выходного диапазона является TrivialType.
Возможная реализация
struct uninitialized_fill_n_fn
{
template<no-throw-forward-range 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 (...) // rollback: destroy constructed elements
{
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 << "Exception!\n";
}
}Вывод:
cppreference cppreference cppreference
Отчеты об ошибках
Следующие отчеты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применено к | Поведение, как опубликовано | Корректное поведение |
|---|---|---|---|
| LWG 3870 | C++20 | Этот алгоритм может создавать объекты в памяти const | Оставлено запрещенным |
См. также
|
(C++20) |
копирует объект в неоинициализированную область памяти, определенную диапазоном (niebloid) |
| копирует объект в неоинициализированную область памяти, определяемую началом и счетчиком (шаблон функции) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/memory/ranges/uninitialized_fill_n