std::ranges::copy_if需包含和容器头文件,c++20起可用,不修改原容器,目标容器须预分配空间或用back_inserter,lambda需显式捕获外部变量,区别于传统copy_if在于接受范围而非迭代器对。

std::ranges::copy_if 基本用法和必要头文件
必须包含 <algorithm></algorithm> 和 <vector></vector>(或对应容器头文件),C++20 起 std::ranges::copy_if 才可用。它不修改原容器,只把满足条件的元素复制到目标迭代器位置——这意味着目标容器得预先分配空间,或用支持插入的迭代器(如 std::back_inserter)。
目标容器没预留空间时怎么避免崩溃
常见错误是传入空 std::vector 的 begin(),导致越界写入。正确做法是用 std::back_inserter 或先调用 reserve():
- 用
std::back_inserter(v):自动调用push_back,安全但可能触发多次内存重分配 - 先估算数量再
v.reserve(n),然后用v.begin()+copy_if,性能更好但需预估 - 直接用
std::vector构造函数配合std::ranges::copy_if不行——它不返回新容器,得手动构造
示例:
std::vector<int> src = {1, 2, 3, 4, 5};
std::vector<int> dst;
std::ranges::copy_if(src, std::back_inserter(dst), [](int x) { return x % 2 == 0; }); // dst = {2, 4}</int></int>
lambda 捕获与作用域变量的陷阱
如果过滤逻辑依赖外部变量(比如阈值、配置),lambda 必须显式捕获,否则编译失败:
-
[threshold](int x) { return x > threshold; }—— 正确,按值捕获 -
[&config](int x) { return x > config.limit; }—— 可行,但要确保config生命周期长于算法执行 - 漏写捕获子句,如
(int x) { return x > threshold; }—— 编译报错:use of undeclared identifier 'threshold'
和传统 std::copy_if 的关键区别
主要差异不在功能,而在接口设计:
-
std::copy_if接收三个迭代器(first, last, result),std::ranges::copy_if接收一个范围(如容器或视图)+ 结果迭代器 + 谓词 -
std::ranges::copy_if支持视图链式组合,比如src | std::views::filter(...) | std::ranges::to<:vector>()</:vector>更简洁,但那是std::ranges::to,不是copy_if - 没有
std::ranges::copy_if的“就地过滤”版本;真要原地删,得用erase-remove惯用法或std::ranges::remove_if+erase
真正容易被忽略的是:它不检查目标空间是否足够——用裸指针或普通数组时,务必自己保证长度够用,否则行为未定义。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











