std::ranges::views::values 不仅适用于关联容器,还适用于任何 value_type 为键值对(如 std::pair)的范围;对 std::vector 等非键值对类型直接使用会因缺少 .second 而编译失败。

std::ranges::views::values 只适用于关联容器吗?
不是。它只适用于“键值对”结构的范围,比如 std::map、std::unordered_map,或者任何满足 value_type 是类似 std::pair<const k v></const> 的自定义容器。对 std::vector<:pair int>></:pair> 也能用,但对 std::vector<int></int> 直接用会编译失败——因为没有 .second 可提取。
常见错误现象:error: no member named 'second' in 'int',本质是视图试图从每个元素取 .second 字段,而原始类型不支持。
- 必须确保源范围的
value_type是可解构为键值对的类型(通常是std::pair或兼容结构体) -
std::map和std::unordered_map天然满足;std::set不行,它没有.second - C++20 起才可用,需开启
-std=c++20编译选项
怎么写一行代码取出 map 的所有 value 并遍历?
最简写法就是管道操作符链式调用,不需要额外变量或 lambda:
for (auto v : my_map | std::ranges::views::values) {
std::cout
<p>注意:这里 <code>v</code> 是 <code>mapped_type</code> 的引用(可能是 <code>const V&</code>),不是拷贝。如果需要修改原 map 中的值,得确认 map 本身非常量且迭代器可写(<code>std::map</code> 迭代器的 <code>.second</code> 是可写的,但 <code>.first</code> 不行)。</p>
- 若
my_map是const std::map<int std::string></int>,则v类型为const std::string& - 若想得到拷贝而非引用,可加
| std::ranges::to<:vector></:vector>,但会触发遍历+分配 - 不能直接对
views::values调用.size()—— 它是 lazy view,无 O(1) 大小信息
和传统 for-loop 或 transform 比,性能有啥区别?
零额外开销。views::values 是纯适配器,不复制数据、不分配内存,底层只是重绑定迭代器的 operator* 返回 it->second。汇编级和手写循环几乎一致。
但要注意:它不改变底层容器的缓存友好性。比如 std::map 本身是红黑树,节点分散在堆上,无论用不用 views,随机访问 .second 都不如 std::vector 连续。
- 对比
for (const auto& p : my_map) { ... p.second ... }:语义等价,性能相同 - 对比
std::transform(..., [](const auto& p){return p.second;}):后者可能触发临时 vector 分配,除非配合std::back_inserter或预分配 - 调试时,
views::values在某些 IDE(如 VS2022)里展开可能显示为未求值表达式,需手动 dereference 查看
为什么有时候编译不过,报 “no matching function for call to ‘values’”?
最常见原因是忘了引入头文件或命名空间。C++20 的 ranges views 分散在多个头文件中,且依赖 ADL(Argument-Dependent Lookup)。
必须同时满足:
- 包含
<ranges></ranges>(不是<algorithm></algorithm>或<iterator></iterator>) - 使用
std::ranges::views::values全名,或using namespace std::ranges::views;(不推荐全局 using) - 确保编译器支持 C++20 的 ranges(GCC 10+、Clang 13+、MSVC 19.30+)
- 检查是否误用了
std::views::values(不存在,std::views下只有filter、transform等通用视图)
容易被忽略的一点:如果 map 是模板参数推导来的(比如函数模板里),而你传入的是右值临时 map,views::values 可能因绑定问题失败——此时显式加上 std::move(my_map) 或改为 const 引用参数更稳妥。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











