std::reverse必须传入一对双向迭代器而非容器本身,正确用法为std::reverse(container.begin(), container.end()),返回void且就地修改原序列。

reverse 函数必须传入迭代器,不能直接传容器
很多人写 reverse(vec) 或 reverse(arr) 直接报错,因为 std::reverse 不接受容器对象,只接受一对双向迭代器(begin 和 end)。它本质上操作的是「一段内存区间」,和容器类型无关。
正确用法是:
std::vector<int> v = {1, 2, 3, 4};
std::reverse(v.begin(), v.end()); // ✅
常见错误现象:error: no matching function for call to 'reverse',往往就是漏了 .begin() 和 .end()。
-
std::array、std::deque、std::list同样适用,只要支持双向迭代器 - C 风格数组需手动传指针:
int a[5] = {1,2,3,4,5}; std::reverse(a, a + 5); - 字符串也行:
std::string s = "hello"; std::reverse(s.begin(), s.end());
reverse 是就地反转,不返回新容器
std::reverse 没有返回值(返回类型是 void),它直接修改原序列。如果你需要保留原数据,得先拷贝:
立即学习“C++免费学习笔记(深入)”;
std::vector<int> v = {1, 2, 3};
auto v_rev = v; // 先拷贝
std::reverse(v_rev.begin(), v_rev.end()); // 再反转副本
容易踩的坑:
- 误以为
v = std::reverse(...)能赋值 —— 编译不过 - 在函数里对参数调用
reverse,却没意识到原容器已被改写(尤其是传引用时) - 对
const容器或子范围(如v.begin()+1, v.end()-1)调用时,确保该范围可写
reverse_iterator 不等于 reverse 函数
别把 std::reverse_iterator 和 std::reverse 搞混。前者只是「反向遍历的迭代器类型」,不改变容器内容;后者才是真反转数据。
比如:
std::vector<int> v = {1,2,3};
for (auto it = v.rbegin(); it != v.rend(); ++it) {
std::cout << *it << " "; // 输出 3 2 1,但 v 本身还是 {1,2,3}
}
而 std::reverse(v.begin(), v.end()) 执行后,v 真变成 {3,2,1}。
-
rbegin()/rend()开销极小,适合只读遍历 - 要永久翻转顺序,必须用
std::reverse或手动 swap - 某些算法(如
std::sort)配合greater<int>()</int>可模拟“逻辑上倒序”,但物理顺序不变
性能与边界:reverse 时间复杂度是 O(n),但要注意迭代器有效性
std::reverse 内部是首尾交换,时间复杂度 O(n/2),空间 O(1),很高效。但有两个易忽略点:
- 传入的两个迭代器必须属于同一容器,且
first可达last(即[first, last)是合法范围),否则行为未定义 - 如果容器在反转过程中被其他线程修改,结果不可预测 —— 它不是线程安全的
- 对空容器或单元素容器调用是安全的:
reverse(v.begin(), v.begin())或reverse(v.begin(), v.begin()+1)都没问题
最常被忽略的是:反转 std::list 时虽然语法一样,但底层是节点指针重连,不是逐个 swap 元素 —— 这不影响使用,但知道这点能避免误判性能。


















