c++oding="utf-8" ?>
std::ranges::views::keys 是泛化适配器,要求元素含 first 成员,兼容 map 等键值容器,返回只读视图,需 c++20 支持,不可随机访问或修改键,不拥有数据需注意生命周期。

std::ranges::views::keys 要求容器有 value_type::first 成员
它不是专为 std::map 设计的“魔法函数”,而是泛化适配器:只要容器元素是类似 std::pair 的结构(即含 first 成员),就能提取键。所以它天然兼容 std::map、std::unordered_map,也兼容 std::vector<:pair std::string>></:pair> 这类自定义键值序列。
但注意:std::map::value_type 是 std::pair<const key t></const>,first 是 const 引用——这意味着你不能通过 views::keys 返回的视图去修改原始键(这符合语义,键本就不该被改)。
必须开启 C++20 且链接标准库范围支持
很多新手卡在这步:编译通过但运行时报错或行为异常。原因常见于:
- 没加
-std=c++20(Clang/GCC)或/std:c++20(MSVC) - 使用了旧版 libc++ 或 libstdc++(GCC 10/Clang 12 之前不完整支持
views::keys) - 忘了
#include <ranges></ranges>和#include <map></map>
最小可跑示例:
#include <ranges>
#include <map>
#include <iostream>
int main() {
std::map<int std::string> m = {{1,"a"}, {2,"b"}, {3,"c"}};
for (auto k : m | std::views::keys) {
std::cout
<h3>不能直接对 keys 视图调用 <code>find</code> 或 <code>operator[]</code>
</h3>
<p><code>std::views::keys(m)</code> 返回的是一个只读的 <code>std::ranges::view</code>,不是容器,也不提供查找接口。它只是把原 map 的键“投影”出来,底层仍依赖原容器迭代。</p>
<p>常见误用:</p>
<ul>
<li>
<code>m | std::views::keys | std::ranges::find(42)</code> —— 错!<code>std::ranges::find</code> 可以用,但效率是 O(n),不如直接查原 map 的 <code>find()</code>(O(log n))</li>
<li>
<code>(m | std::views::keys)[2]</code> —— 错!keys 视图不保证随机访问(<code>std::map</code> 的迭代器是双向而非随机),会编译失败</li>
<li>试图用 <code>std::views::keys(m).begin()->second</code> —— 错!keys 视图的元素是 <code>key_type</code>(如 <code>int</code>),没有 <code>second</code>
</li>
</ul>
<h3>与传统 for-loop 和 <code>std::transform</code> 的性能差异极小,但语义更清晰</h3>
<p>它不分配内存、不拷贝键,只是包装迭代器,和手写 <code>for (const auto& p : m) { use(p.first); }</code> 几乎等价。但它让意图一目了然:你明确在“处理键序列”。</p>
<p>适合场景:</p>
<ul>
<li>配合管道操作,比如 <code>m | std::views::keys | std::views::filter(&is_even) | std::views::take(5)</code>
</li>
<li>传给接受 <code>std::ranges::input_range</code> 的算法(如 <code>std::ranges::all_of</code>)</li>
<li>避免手写 <code>p.first</code>,减少拼写错误</li>
</ul>
<p>真正要注意的其实是生命周期:视图不拥有数据,<code>m</code> 必须活过视图使用期,否则迭代会悬垂。</p></int></iostream></map></ranges>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











