std::ranges::sort(v)更安全清晰,直接传容器;视图组合filter/transform惰性高效;erase_if一步删除符合条件元素。
用
替代
,直接传容器而非迭代器
传统
必须传入
和
迭代器,容易写错边界或搞混顺序;
接收整个范围(如
、
),语义更清晰,也自动适配自定义范围。
常见错误:混用旧式迭代器和 ranges 算法,比如对
调用
—— 这会退化为传统行为,失去 ranges 的优势,且可能因迭代器类型不匹配编译失败。
正确写法:直接传容器对象,
支持自定义比较:
仅对子范围排序:用
或切片视图,例如
(注意:这会排序前 5 个元素的副本,需用
+
配合可写视图,实际中更推荐
)
用
和
替代手写循环
传统方式要开新容器、遍历、条件判断、push_back……容易漏
、误用
和
、索引越界。Ranges 视图是惰性求值的,组合起来不产生中间容器,内存友好,逻辑也更接近自然语言。
关键点:视图对象本身不拥有数据,不能脱离原容器生命周期使用;一旦原容器被移动或销毁,再访问视图会 UB。
立即学习
“
C++免费学习笔记(深入)
”;
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
接收一元谓词,返回满足条件的元素引用
接收一元函数,返回转换后的新值(注意:若返回临时对象,需确保生命周期足够长)
链式调用顺序即执行顺序:
先过滤再转换
要落地为容器,必须显式构造,例如
用
+
安全删除满足条件的元素
旧式
+
(erase–remove 惯用法)易出错:忘记
、迭代器失效、对
等非连续容器效率低。C++20 提供
(针对容器)和
(直接按条件删),语义明确、一步到位。
注意:
是容器专属算法,只接受容器(如
、
),不接受任意范围(如视图)。若你手头是个视图,得先确认它背后是否可修改且支持擦除。
返回值是被删元素个数,可用于断言或日志
对
,内部仍做移动,但接口屏蔽了细节;对
,是真正的 O(n) 删除
组合视图时小心求值时机和临时对象生命周期
这是最常被忽略的坑:视图是轻量级对象,但其内部可能绑定临时容器或 lambda 捕获。一旦绑定源离开
作用域
,继续使用视图就是悬垂引用。
典型错误场景:函数返回一个由局部容器生成的视图、在 lambda 中捕获局部变量后用于
、把
和临时 vector 组合后存为成员变量。
避免返回视图:改用返回
或接收输出迭代器
lambda 捕获尽量用值捕获(
),不用引用(
)除非你能保证
生命周期覆盖视图使用期
调试技巧:对怀疑悬垂的视图,加一句
测试——若崩溃或返回异常大值,大概率是生命周期问题
std::ranges::sortstd::sortstd::sortbegin()end()std::ranges::sortstd::vectorstd::arraystd::vectorstd::ranges::sort(v.begin(), v.end())std::ranges::sort(v)std::ranges::sort(v, std::greater{})std::ranges::subrangestd::ranges::sort(v | std::views::take(5))std::views::takestd::ranges::sortstd::ranges::sort(std::ranges::subrange(v.begin(), v.begin() + 5))std::vector v = {3, 1, 4, 1, 5};
std::ranges::sort(v); // ✅ 直接、安全、可读
// v 变为 {1, 1, 3, 4, 5} std::views::filterstd::views::transformreserve===filtertransformv | filter(...) | transform(...)std::vector(v | std::views::filter(...) | std::views::transform(...)) std::vector v = {1, 2, 3, 4, 5, 6};
auto evens_squared = v
| std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * x; });
std::vector result(evens_squared.begin(), evens_squared.end());
// result 为 {4, 16, 36}
std::ranges::find_ifstd::ranges::eraseremove_iferaseeraseliststd::ranges::erasestd::ranges::erase_ifstd::ranges::erase_ifstd::vectorstd::dequestd::ranges::erase_if(v, [](int x) { return x 删除所有负数std::vectorstd::liststd::vector v = {−2, 3, −1, 7, 0, −5};
auto n = std::ranges::erase_if(v, [](int x) { return x < 0; });
// v 变为 {3, 7, 0},n == 3 transformstd::views::iotastd::vector[x][&x]xstd::ranges::size(view)// ❌ 危险:view 绑定到局部 vector,函数返回后失效
auto get_even_view() {
std::vector local = {1, 2, 3, 4};
return local | std::views::filter([](int x) { return x % 2 == 0; });
}
// ✅ 安全:立即物化为 vector
auto get_even_vec() {
std::vector local = {1, 2, 3, 4};
return std::vector(local | std::views::filter([](int x) { return x % 2 == 0; }));
}
