std::ranges::reverse 不是视图操作,而是一个就地逆序的算法,返回 void 且修改原容器;反向视图应使用 std::ranges::views::reverse。

std::ranges::reverse 是视图操作吗?
不是。std::ranges::reverse 是一个算法,作用于迭代器范围,**不返回视图,也不生成新序列**;它直接修改原容器内元素的顺序。如果你想要“反向视图”(即不改变原数据、仅提供反向遍历接口),该函数完全用错方向。
常见误用:写成 auto reversed = std::ranges::reverse(v); —— 这会编译失败,因为 std::ranges::reverse 返回 void。
- 它只接受可变迭代器范围(
std::ranges::bidirectional_range且可写) - 要求元素可移动或可交换(底层调用
std::iter_swap) - 适用于
std::vector、std::deque、std::list等,但不适用于std::array的字面量或只读视图(如std::ranges::subrange指向 const 数据)
想得到反向视图,该用什么?
用 std::ranges::views::reverse —— 这才是真正的视图适配器,返回一个懒计算的反向视图,不修改原数据,也不复制元素。
示例:
std::vector<int> v = {1, 2, 3, 4};
auto rev_view = v | std::ranges::views::reverse;
for (int x : rev_view) {
std::cout
<ul>
<li>
<code>views::reverse</code> 可链式组合:<code>v | views::filter([](int x){return x%2==0;}) | views::reverse</code>
</li>
<li>底层不分配内存,每次迭代时从尾向前推进迭代器,时间复杂度 O(1) per element,空间 O(1)</li>
<li>仅支持双向迭代器以上(<code>random_access_range</code> 或 <code>bidirectional_range</code>),不支持单向链表(如 <code>std::forward_list</code>)</li>
</ul>
<h3>std::ranges::reverse 实际怎么用?</h3>
<p>当你确实需要**就地翻转容器内容**时,才调用它。典型场景:预处理、缓存重排、算法中间步骤。</p>
<p>正确写法:</p>
<pre class="brush:php;toolbar:false;">std::vector<:string> words = {"hello", "world"};
std::ranges::reverse(words); // ✅ 修改 words 为 {"world", "hello"}
// 或指定范围:
std::ranges::reverse(words.begin() + 1, words.end()); // 仅翻转后缀
</:string>
- 参数可以是容器、数组、或一对迭代器(
begin/end) - 对
std::array有效:std::array<int> a = {1,2,3}; std::ranges::reverse(a);</int> - 对
std::string同样适用:std::string s = "abc"; std::ranges::reverse(s); // s → "cba" - 注意:若传入
const容器或临时对象(如std::vector{1,2,3}),编译失败 —— 它需要左值且可修改
容易混淆的命名和头文件
std::ranges::reverse 和 std::ranges::views::reverse 名字太像,但语义和头文件都不同。
-
std::ranges::reverse在<algorithm></algorithm>中(C++20 起扩展支持 ranges) -
std::ranges::views::reverse在<ranges></ranges>中,且需启用 C++20 并确保标准库实现支持(GCC 10+、Clang 13+、MSVC 19.30+) - 别漏掉
using namespace std::ranges::views;或完整写std::ranges::views::reverse,否则编译器找不到 - 若用 GCC 编译报错 “no match for ‘operator|’”,大概率是没包含
<ranges></ranges>或未开启-std=c++20
最常被忽略的一点:视图是惰性的,views::reverse 不产生副本,但一旦原容器析构或迭代器失效,视图立即不可用 —— 它不延长底层生命周期。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











