C++中ranges::copy_if与配合views::filter的vector迭代器构造对比
过滤元素存入vector两种实现方案对比
以下是两种C++实现方案的对比和选择建议:
你提到的两种实现代码如下:
#include <algorithm> #include <iostream> #include <ranges> #include <vector> #include <utility> #include <fmt/ranges.h> const std::vector<int> vals{1,2,3,47,8472}; const auto filter_pred = [](const int i){return i%2==0;}; // ranges::copy_if 方案 void fna(){ std::vector<int> result; std::ranges::copy_if(vals, std::back_inserter(result), filter_pred); std::cout << fmt::format("{}", result) << std::endl; } // filter_view + 迭代器构造方案 void fn1(){ auto filtered = vals | std::views::filter(filter_pred); std::vector<int> result {filtered.begin(), filtered.end()}; std::cout << fmt::format("{}", result) << std::endl; } std::vector<int> fna_val(){ std::vector<int> result; std::ranges::copy_if(vals, std::back_inserter(result), filter_pred); return result; } std::vector<int> fn1_val(){ auto filtered = vals | std::views::filter(filter_pred); return {filtered.begin(), filtered.end()}; } int main(){ fna(); fn1(); std::cout << fmt::format("{}", fna_val()) << std::endl; std::cout << fmt::format("{}", fn1_val()) << std::endl; }
差异与选择判断
- 性能层面二者几乎没有差异:因为过滤后的元素数量都是未知的,都无法提前预分配空间,编译器优化后生成的汇编代码基本一致,不需要出于性能考量选择某一种。
- 兼容性与编译速度:如果项目使用C++17及更早版本,或者不需要用到其他 ranges 特性,优先选
std::copy_if方案,不需要引入<ranges>头文件,编译速度更快,兼容性更好。 - 代码可读性与可维护性:C++20及以上版本优先选
filter_view+迭代器构造方案:这是声明式的写法,先明确声明过滤规则,再直接构造目标容器,不需要声明可变的中间容器,代码意图更清晰;如果后续需要新增映射、切片等其他数据处理操作,直接在视图管道后追加对应views操作即可,后续的容器构造逻辑不需要修改,可扩展性远高于copy_if方案。 - 版本升级潜力:C++23已经支持vector直接从范围构造,不需要显式调用
.begin()和.end(),现有filter_view方案的代码可以无缝升级为更简洁的写法:std::vector<int> result{vals | std::views::filter(filter_pred)}; - 特殊场景选择
ranges::copy_if:如果是往已有的容器中追加过滤后的元素,而非新建容器,只能选择ranges::copy_if配合插入迭代器实现,范围构造仅适用于新建容器的场景。
内容的提问来源于stack exchange,提问作者NoSenseEtAl
相关产品推荐
相关产品推荐

