std::ranges::copy_if需包含和容器头文件,c++20起可用;目标空间须预先分配,否则未定义行为;推荐filter_view+to替代以避免容量错误。

std::ranges::copy_if 基本用法和必要头文件
必须包含 <algorithm></algorithm> 和 <vector></vector>(或对应容器头文件),C++20 起才可用。它不修改原容器,只把满足条件的元素复制到目标迭代器起始位置——这意味着目标空间必须预先分配好,否则行为未定义。
-
std::ranges::copy_if接收三个参数:源范围(std::ranges::range)、目标起始迭代器、谓词(可调用对象) - 目标容器不能是空的
std::vector且没预留空间;否则copy_if会越界写入 - 返回类型是
std::ranges::copy_if_result<it o></it>,其中O是输出迭代器类型,一般无需显式接收
目标容器如何预分配空间(最常踩的坑)
很多人直接传 dest.begin() 却忘了 dest 是空的,结果触发未定义行为。正确做法是先 resize 或 reserve + back_inserter,但注意:back_inserter 不符合 std::output_iterator 对随机访问的要求,std::ranges::copy_if 不接受它。
- 安全做法:用
dest.resize(count),其中count是预期元素个数(可先用std::ranges::count_if预估) - 更通用做法:用
std::vector的reserve()+std::back_inserter→ 这不行,得换用std::ranges::copy_if的替代方案:std::ranges::copy+std::ranges::filter_view - 推荐组合:用
std::ranges::filter_view+std::ranges::to<:vector></:vector>(需<ranges></ranges>和<vector></vector>)
filter_view + to 替代方案(更安全直观)
如果你只是想“过滤后得到新 vector”,std::ranges::copy_if 并非最优路径;std::ranges::filter_view 惰性求值 + std::ranges::to 更贴合意图,且自动处理内存分配。
#include <ranges>
#include <vector>
#include <algorithm><p>std::vector<int> src = {1, 2, 3, 4, 5, 6};
auto filtered = src | std::views::filter([](int x) { return x % 2 == 0; })
| std::ranges::to<:vector>();
// filtered == {2, 4, 6}</:vector></int></p></algorithm></vector></ranges>
-
std::views::filter返回 view,不拷贝数据;std::ranges::to<t></t>才真正构造目标容器 - 编译器能优化掉中间临时对象,性能不输
copy_if+ 预分配 - 无需手动计数、resize,避免了绝大多数生命周期和容量错误
copy_if 仍适用的场景(比如复用已有缓冲区)
只有当你明确需要复用一段已分配好的内存(例如固定大小的数组、环形缓冲区、或与硬件对齐的 buffer),std::ranges::copy_if 才有不可替代价值。
- 示例:向 C 风格数组写入过滤结果:
int out[100]; auto res = std::ranges::copy_if(src, out, [](int x){return x>10;}); - 务必确认
out大小 ≥ 满足条件的元素个数,否则溢出 - 返回值
res.out指向写入末尾,可用于后续截断或计算实际长度:size_t n = res.out - out;
真正难的不是写对语法,而是判断该不该用 copy_if —— 大多数业务代码里,filter_view + to 更直白、更安全、更少出错。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











