std::ranges::views::repeat 是 C++20 引入的惰性视图适配器,用于生成无限或指定次数重复同一值的序列;它不分配内存、不复制元素,仅按需返回值,需配合 views::take 等有界适配器使用以避免死循环。

std::ranges::views::repeat 是什么,它能做什么
std::ranges::views::repeat 是 C++20 引入的懒求值视图适配器,用于生成无限(或指定次数)重复某个值的视图。它不分配内存,也不复制元素,只在访问时按需返回同一个值 —— 所以适合用作占位、填充、测试数据生成等场景。
注意:它默认生成无限视图,必须配合 std::ranges::views::take 或其他有界适配器使用,否则遍历会死循环;直接用 for (auto x : std::ranges::views::repeat(42)) 会卡死。
如何安全构造一个有限长度的重复视图
最常见误用是忽略长度控制。正确做法是链式组合 std::ranges::views::repeat 和 std::ranges::views::take:
auto v = std::ranges::views::repeat(7) | std::ranges::views::take(5);
这生成一个含 5 个 7 的视图。要点:
立即学习“C++免费学习笔记(深入)”;
-
std::ranges::views::repeat接收一个值(可 const、可右值),类型推导为该值的 cv-unqualified 类型 -
std::ranges::views::take必须放在管道右侧,且参数是整型常量表达式或运行时整数(但后者需确保不超范围) - 不能写成
std::ranges::views::take(5) | std::ranges::views::repeat(7)—— 顺序错误,编译失败 - 若重复对象是临时对象(如
std::string{"hello"}),要确保其生命周期覆盖视图使用期,否则引发悬垂引用
与 std::vector::assign 或 std::fill 的区别在哪
std::ranges::views::repeat 不修改容器,也不预分配内存,它只是“描述”一个逻辑序列;而 std::vector::assign 或 std::fill 是立即求值、副作用明确的操作。
适用场景差异:
- 需要延迟计算、组合其他视图(如
repeat(x) | transform(f) | filter(g))→ 选views::repeat - 需要真实存储、随机访问、多次迭代 → 用
std::vector+assign更稳妥 - 对已有容器填充固定值 →
std::fill更直接,无视图开销 -
views::repeat的迭代器是 input_iterator_tag,不支持operator-或随机跳转
常见编译错误和类型陷阱
典型报错:error: no matching function for call to 'repeat',通常因头文件缺失或标准版本未启用。
必须确认:
- 编译器支持 C++20(GCC ≥10、Clang ≥13、MSVC ≥19.30),并开启
-std=c++20(或更高) - #include <ranges>,不是 <algorithm> 或 <iterator>
- 重复值不能是纯右值引用类型(如
int&&),但可以是int、const int&、std::string等可拷贝/可移动类型 - 若传入 lambda 或函数对象,需确保其可默认构造且无捕获(因为视图内部需保存一份副本)
无限视图本身合法,但任何试图获取 size()、begin() == end() 判定、或用在要求 sized_range 的算法里(如 std::ranges::sort),都会编译失败。


















