std::views::chunk_by按相邻元素谓词结果翻转切块,非固定长度分组;需满足forward_range,谓词须纯二元无状态,否则导致编译失败或未定义行为。

它不是按固定长度切块的工具,std::views::chunk_by 只响应相邻元素间谓词结果的“翻转”——true → false 或 false → true 时才切一刀。想实现“每 3 个一组”,该用 std::views::chunk(3),不是它。
chunk_by 的触发逻辑:只看 (a, b) 这一对,不看全局
它把输入序列扫一遍,对每个位置 i(从 1 开始),拿 *(it + i - 1) 和 *(it + i) 调用谓词,即 (前一元素, 当前元素)。只要这个调用返回 false,就在当前元素之前切开,让它成为新块起点。
这意味着:
- 首个元素永远属于第一块,不参与任何谓词调用
-
{1,1,2,2,2,3,1}配合std::equal_to{}→ 得到{1,1}、{2,2,2}、{3}、{1},不是按“所有 1 归一堆”来分 - 谓词写成
[&](int a, int b) { return a % 2 == b % 2; },{1,3,5,2,4,6,7}分成三块:{1,3,5}、{2,4,6}、{7}—— 最后一个7和前面6奇偶不同,所以单成一块 - 若谓词恒为
true(如全相同值),整个范围就只有 1 个块;若恒为false(如严格递增),每个元素都是独立块
谓词必须是纯二元、无状态、可复制的可调用对象
签名强制为 bool(T, T),且不能依赖外部可变状态。否则视图对象不可复制,后续管道操作(比如接 std::views::transform)会编译失败。
常见问题包括:
- 捕获局部变量并修改它:
[count](auto, auto) mutable { return ++count & 1; }→ 错误,行为未定义 - 捕获引用或非常量指针:
[&config](auto a, auto b) { return a.flag == config.flag; }→ 若config是栈上临时对象,视图可能持悬垂引用 - 参数类型不匹配:输入是
const std::vector<int>::value_type&</int>,谓词却声明为int值参 → 可能引发隐式拷贝或编译警告 - 安全写法示例:
[](int a, int b) { return a / 10 == b / 10; }(按十位分组)、std::equal_to{}、std::less{}
输入必须是 forward_range,std::list 和 std::forward_list 不行
std::views::chunk_by 内部需要缓存上一个元素,并多次解引用同一迭代器位置(比如回退比较),因此要求输入满足 std::forward_range 概念。这排除了仅满足 input_range 的单次读取流,也排除了 std::list 和 std::forward_list —— 它们的迭代器不支持多遍历同一节点。
典型错误:
-
std::list<int> l = {1,2,2,3}; auto v = l | std::views::chunk_by(std::equal_to{});</int>→ 编译失败,报错指向forward_range约束不满足 - 临时容器直接传入:
std::vector{1,2,3} | std::views::chunk_by(pred)→ 可能导致悬垂引用,应先绑定具名变量 - 正确替代:用
std::vector、std::array、原生数组、std::string;C 风格数组可用std::span包装后再接入
chunk_by_view 迭代器比 chunk 更容易失效
它内部维护一个“当前块起始迭代器”,每次推进都要和上一个位置做比较。一旦原始容器发生任何改动(std::vector::push_back 导致重分配、erase、insert),所有已构造的 chunk_by_view::iterator 立即失效 —— 而 std::views::chunk 因只依赖索引偏移,在随机访问容器中反而更稳定。
这意味着:
- 不要在循环中边遍历
chunk_by_view边修改原容器 - 若需长期持有块视图,应尽快完成消费(如转成
std::vector<:vector>></:vector>),避免跨作用域保留chunk_by_view对象 - 调试时若遇到
use of deleted function或copy constructor is implicitly deleted,优先检查谓词是否捕获了不可复制的对象
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











