# std::ranges::uninitialized_fill

< cpp‎ | memory

定义于头文件 `<memory>` |  |
调用签名 |  |
template< no-throw-forward-iterator I, no-throw-sentinel-for<I> S, class T > requires std::constructible_from<std::iter_value_t<I>, const T&> I uninitialized_fill( I first, S last, const T& x ); | (1) | (C++20 起)
template< no-throw-forward-range R, class T > requires std::constructible_from<ranges::range_value_t<R>, const T&> ranges::borrowed_iterator_t<R> uninitialized_fill( R&& r, const T& x ); | (2) | (C++20 起)

1) 在范围 `[first, last)` 所指代的未初始化内存区域构造给定值 `x` 的 \(\scriptsize N\)N 个副本，其中 \(\scriptsize N\)N 为 ranges::distance(first, last) 。
函数所拥有的效果等价于：

    for (; first != last; ++first) {
        ::new (
            const_cast<void*>(static_cast<const volatile void*>(std::addressof(*first)))
            ) std::remove_reference_t<std::iter_reference_t<I>>(x);
    }
    return first;

若在初始化期间抛异常，则以未指定顺序销毁已构造的对象。
2) 同 (1) ，但以 `r` 为源范围，如同以 ranges::begin(r) 为 `first` 并以 ranges::end(r) 为 `last` 。

此页面上描述的仿函数实体是 niebloid ，即：

- 调用它们中的任何一者时不可指定显式模板实参。
- 它们无一对实参依赖查找可见。
- 在通常无限定查找寻找函数调用运算符左侧的名称找到它们之一时，它禁止实参依赖查找。

实际上，它们能以函数对象，或以某些特殊编译器扩展实现。

### 参数

first, last | - | 要初始化的元素范围
r | - | 要初始化的元素范围
value | - | 用以构造元素的值

### 返回值

等于 `last` 的迭代器。

### 复杂度

\(\scriptsize\mathcal{O}(N)\)𝓞(N) 。

### 异常

构造目标范围中的元素时抛出的异常，若存在。

### 注解

若输出范围的值类型为 平凡类型 (TrivialType) ，则实现可以提升 ranges::uninitialized_fill 的效率，例如用 ranges::fill 。

### 可能的实现

    struct uninitialized_fill_fn {
        template <no-throw-forward-iterator I, no-throw-sentinel-for<I> S, class T>
        requires std::constructible_from<std::iter_value_t<I>, const T&>
        I operator()( I first, S last, const T& x ) const {
            I rollback {first};
            try {
                for (; !(first == last); ++first)
                    ranges::construct_at(std::addressof(*first), x);
                return first;
            } catch (...) { // 回滚：销毁已构造的元素
                for (; rollback != first; ++rollback)
                    ranges::destroy_at(std::addressof(*rollback));
                throw;
            }
        }

        template <no-throw-forward-range R, class T>
        requires std::constructible_from<ranges::range_value_t<R>, const T&>
        ranges::borrowed_iterator_t<R>
        operator()( R&& r, const T& x ) const {
            return (*this)(ranges::begin(r), ranges::end(r), x);
        }
    };

    inline constexpr uninitialized_fill_fn uninitialized_fill{};

### 示例

    #include <iostream>
    #include <memory>
    #include <string>

    int main()
    {
        constexpr int n {4};
        alignas(alignof(std::string)) char out[n * sizeof(std::string)];

        try
        {
            auto first {reinterpret_cast<std::string*>(out)};
            auto last {first + n};
            std::ranges::uninitialized_fill(first, last, "▄▀▄▀▄▀▄▀");

            int count {1};
            for (auto it {first}; it != last; ++it) {
                std::cout << count++ << ' ' << *it << '\n';
            }

            std::ranges::destroy(first, last);
        }
        catch(...)
        {
            std::cout << "Exception!\n";
        }
    }

输出：

    1 ▄▀▄▀▄▀▄▀
    2 ▄▀▄▀▄▀▄▀
    3 ▄▀▄▀▄▀▄▀
    4 ▄▀▄▀▄▀▄▀

### 参阅

ranges::uninitialized_fill_n (C++20) | 复制一个对象到起始与计数所定义的未初始化的内存区域 (niebloid)
uninitialized_fill | 复制一个对象到以范围定义的未初始化内存区域 (函数模板)