std::iota

< cpp‎ | algorithm
在标头 <numeric> 定义
template< class ForwardIt, class T >
void iota( ForwardIt first, ForwardIt last, T value );
(C++11 起)
(C++20 起为 constexpr)

以始于 value 并重复地求值 ++value 的顺序递增值填充范围 [firstlast)

等价操作(假设 ++value 会返回自增后的值):

*first   = value;
*++first = ++value;
*++first = ++value;
*++first = ++value;
// 抵达 “last” 前重复

如果满足以下任意条件,那么程序非良构:

  • T 不可转换到 ForwardIt值类型
  • 表达式 ++val 非良构,其中 valT 类型变量。

参数

first, last - value 开始按顺序递增的值所填充的范围
value - 要存储的初始值

复杂度

自增与赋值 std::distance(first, last) 次。

可能的实现

template<class ForwardIt, class T>
constexpr // C++20 起
void iota(ForwardIt first, ForwardIt last, T value)
{
    for (; first != last; ++first, ++value)
        *first = value;
}

注解

此函数命名来源于编程语言 APL 中的整数函数 。它是 C++98 所不曾包含的 STL 组件之一,但最终在 C++11 进入了标准库。

示例

下列代码应用 std::shufflestd::list 的迭代器组成的 vector,因为不能直接应用 std::shufflestd::list。用 std::iota 填充两个容器。

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <list>
#include <numeric>
#include <random>
#include <vector>
 
class BigData // 复制操作低效
{
    int data[1024]; /* 一些原始数据 */
public:
    explicit BigData(int i = 0) { data[0] = i; /* ... */ }
    operator int() const { return data[0]; }
    BigData& operator=(int i) { data[0] = i; return *this; }
    /* ... */
};
 
int main()
{
    std::list<BigData> l(10);
    std::iota(l.begin(), l.end(), -4);
 
    std::vector<std::list<BigData>::iterator> v(l.size());
    std::iota(v.begin(), v.end(), l.begin());
    // 用(指向原数据的)迭代器的向量来避免昂贵复制操作,
    // 也是因为无法直接对 std::list 应用 std::shuffle(见下)
 
    std::shuffle(v.begin(), v.end(), std::mt19937{std::random_device{}()});
 
    std::cout << "list l 原来的内容:\t\t";
    for (const auto& n : l)
        std::cout << std::setw(2) << n << ' ';
    std::cout << '\n';
 
    std::cout << "通过打乱的 v 看到的 l 的内容:\t";
    for (const auto i : v)
        std::cout << std::setw(2) << *i << ' ';
    std::cout << '\n';
}

可能的输出:

list l 原来的内容:          -4 -3 -2 -1  0  1  2  3  4  5
通过打乱的 v 看到的 l 的内容:      -1  5 -4  0  2  1  4 -2  3 -3

参阅

由通过重复对某个初值自增所生成的序列组成的 view
(类模板) (定制点对象)
将一个给定值复制赋值给一个范围内的每个元素
(函数模板)
(C++20)
以特定值向范围的各元素赋值
(niebloid)
将相继的函数调用结果赋值给一个范围中的每个元素
(函数模板)
保存函数结果到一个范围中
(niebloid)
(C++23)
用从起始值开始连续递增的值填充一个范围
(niebloid)