c++oding="utf-8" ?>
std::ranges::copy_if拷贝偶数的基本写法是配合lambda判断并用std::back_inserter目标容器,如std::ranges::copy_if(src, std::back_inserter(dest), [](int x){return x%2==0;});不可直接传dest.begin()以免越界,且需c++20支持。

std::ranges::copy_if 拷贝偶数的基本写法
直接用 std::ranges::copy_if 配合 lambda 判断偶数,目标容器需提前分配空间或用 back_inserter。它不自动扩容,盲目传空 std::vector 会导致无输出。
常见写法是配合 std::back_inserter:
std::vector<int> src = {1, 2, 3, 4, 5, 6};
std::vector<int> dest;
std::ranges::copy_if(src, std::back_inserter(dest), [](int x) { return x % 2 == 0; });
// dest == {2, 4, 6}
</int></int>
- 必须传迭代器适配器(如
std::back_inserter),不能直接传dest.begin()—— 否则越界写入未初始化内存 - lambda 中用
x % 2 == 0即可,负数在 C++ 中取模结果符号依赖实现,但偶数判断仍成立(-4 % 2 == 0为 true) - 若源容器含
int以外类型(如size_t),注意% 2仍安全,但避免对有符号/无符号混用做位运算假设
想预分配空间提升性能?得手动 resize
std::ranges::copy_if 不提供“先计数再拷贝”的原子操作,想避免多次内存重分配,就得两趟遍历:先用 std::ranges::count_if 算偶数个数,再 resize 目标容器,最后用普通迭代器拷贝。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
std::vector<int> src = {1, 2, 3, 4, 5, 6};
std::vector<int> dest;
dest.resize(std::ranges::count_if(src, [](int x) { return x % 2 == 0; }));
std::ranges::copy_if(src, dest.begin(), [](int x) { return x % 2 == 0; });
</int></int>
- 第二步传
dest.begin()是安全的,因为已确保容量足够 - 如果源数据极大且偶数比例极低,两趟遍历可能比
back_inserter的摊还成本还慢,别盲目优化 -
resize后的dest大小等于偶数个数,但内容未初始化——copy_if会覆盖前 N 个位置,其余元素不会被访问,没问题
编译失败?检查 C++20 和标准库支持
报错类似 ‘copy_if’ is not a member of ‘std::ranges’,基本是编译器或标准库没跟上 C++20 范围库。
- Clang 10+、GCC 10+、MSVC 19.28+ 支持,但 GCC 10 默认不启用
std::ranges,需加-std=c++20且确保 libstdc++ 版本够新 - 用
__cpp_lib_ranges宏检测:#if __cpp_lib_ranges >= 201911L - 若环境受限,退化到传统
std::copy_if+std::back_inserter,行为一致,只是不支持范围概念(如容器直接传参)
和传统 std::copy_if 有什么实质区别?
核心差异在接口:C++20 版接受容器或范围(如 std::vector、std::span、自定义 range),老版只认迭代器对。
- 旧写法必须写
std::copy_if(src.begin(), src.end(), ...);新写法直接std::ranges::copy_if(src, ...) - 两者算法逻辑、复杂度、异常安全完全一致,没有性能差别
- 如果你用
std::views::filter组合,那才是惰性求值;copy_if始终是立即执行、产生新容器的“物化”操作
真正容易被忽略的是:哪怕用了 std::ranges::copy_if,它也不会帮你管理目标容器生命周期——back_inserter 看似方便,但背后是反复调用 push_back,对非 trivial 类型可能触发多次构造/移动。如果拷贝的是大对象,且你知道大概数量,预分配仍是更稳的选择。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










