最稳妥方法是用 std::vector 动态收集偶数,因其自动扩容、异常安全且语义清晰;若需原生数组则须两趟遍历统计再分配,避免越界或浪费。

用 std::vector 动态收集偶数最稳妥
原生 C++ 数组(如 int arr[10])长度固定,无法在遍历时动态扩容,硬要“提取到新数组”就得预先算好偶数个数或用额外空间——这既麻烦又容易越界。实际开发中,直接用 std::vector<int></int> 是更自然的选择。
它自动管理内存,支持 push_back(),语义清晰,且与算法配合顺畅:
std::vector<int> src = {1, 2, 3, 4, 5, 6};
std::vector<int> evens;
for (int x : src) {
if (x % 2 == 0) evens.push_back(x);
}
// evens 现在是 {2, 4, 6}
</int></int>
- 别用
new int[n]手动分配再delete[]:易忘释放、不异常安全 - 如果必须返回原生数组(比如对接 C 接口),等收集完再用
evens.data()取指针,但生命周期必须由调用方保证 -
x % 2 == 0对负数也成立(如-4 % 2是 0),无需额外处理符号
用 std::copy_if + back_inserter 更简洁
如果你倾向 STL 算法风格,std::copy_if 配合 std::back_inserter 能一行完成筛选,语义更纯粹,且避免手写循环出错:
std::vector<int> src = {1, 2, 3, 4, 5, 6};
std::vector<int> evens;
std::copy_if(src.begin(), src.end(), std::back_inserter(evens),
[](int x) { return x % 2 == 0; });
</int></int>
-
std::back_inserter让copy_if自动调用push_back,不用预估容量 - lambda 中用
x % 2 == 0比x & 1 == 0更可读;位运算虽快,但对偶数判断无实质优势,反而可能误导(比如-1 & 1是 1,但-1不是奇数?其实是,但逻辑已绕远) - 如果源数据很大,可先调用
evens.reserve(src.size() / 2)减少内存重分配次数
原生数组场景:必须知道偶数个数才能安全复制
如果输入确实是 C 风格数组(如函数参数为 int arr[], size_t n),且明确要求输出也是原生数组,那必须两趟遍历:第一趟数偶数个数,第二趟填值。跳过计数直接分配会导致缓冲区溢出或浪费空间:
int src[] = {1, 2, 3, 4, 5, 6};
size_t n = sizeof(src) / sizeof(src[0]);
// 第一趟:统计
size_t count = 0;
for (size_t i = 0; i
- 忘记
delete[]是常见内存泄漏源;改用std::unique_ptr<int></int>可自动管理,但不如vector直观 - 若
count为 0,new int[0]合法但返回空指针,需检查 - 别用
malloc/free:C++ 中混合使用会引发未定义行为(如调用free释放new的内存)
性能与边界注意点
偶数提取本身开销极小,瓶颈通常不在取模运算,而在内存访问模式和容器操作:
-
std::vector的push_back在容量不足时会重新分配+拷贝,reserve能消除这部分抖动 - 对
int等 trivial 类型,std::vector和原生数组性能几乎无差别;但std::vector的迭代器调试友好、支持范围 for、可移动,综合成本更低 - 如果数组含
INT_MIN,abs(x) % 2会溢出(abs(INT_MIN)未定义),但直接x % 2 == 0没问题 - 多线程环境下,多个线程不能同时往同一个
vector写,需加锁或每个线程用独立容器再合并
真正该花时间想的,不是“怎么提取”,而是“提取后怎么用”——如果只是遍历打印,甚至没必要存新容器,直接在原循环里加个判断更省事。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











