用std::swap逐对交换最直接可靠,编译器通常内联为三条汇编指令,比手动临时变量更安全可读;需遍历至size/2,否则数组不变。

用 std::swap 逐对交换最直接可靠
不需要手写临时变量,std::swap 是 C++ 标准库提供的零开销抽象,编译器通常会内联为三条汇编指令(加载、交换、存储),比手动写临时变量更安全且可读性更好。适用于任意可复制/移动类型的数组,包括自定义类。
常见错误是只遍历到 size 而非 size / 2,导致元素被换回去,最终数组不变:
int arr[] = {1, 2, 3, 4, 5};
size_t n = sizeof(arr) / sizeof(arr[0]);
for (size_t i = 0; i < n / 2; ++i) {
std::swap(arr[i], arr[n - 1 - i]); // ✅ 正确:只跑前半段
}
// 结果:{5, 4, 3, 2, 1}
原地翻转用 std::reverse 更简洁
如果目标就是整个数组前后互换(即翻转),std::reverse 是语义最清晰、不易出错的选择。它内部实现就是调用 std::swap,但封装了边界逻辑,避免手算下标越界或循环范围错误。
- 支持任意迭代器范围,不限于原生数组;
std::vector、std::array同样适用 - 注意传入的是左闭右开区间:
std::reverse(arr, arr + n),不是arr + n - 1 - 对
std::vector使用时,务必用.begin()和.end(),而非下标运算
int arr[] = {10, 20, 30};
std::reverse(arr, arr + 3); // ✅ 翻转后:{30, 20, 10}
用指针算术做“双指针”交换要注意边界
纯 C 风格的双指针法在 C++ 中仍可用,但容易因指针越界或条件判断失误出错。尤其当数组长度为 0 或 1 时,left 判断必须严格,否则可能访问非法内存。
立即学习“C++免费学习笔记(深入)”;
-
left从arr开始,right从arr + n - 1开始 - 循环条件必须是
left ,不能是 <code>left (奇数长度时中间元素会和自己 swap,无害但多余) - 每次循环后要
++left和--right,顺序不能颠倒,否则某次可能跳过交换
int* left = arr;
int* right = arr + n - 1;
while (left < right) {
std::swap(*left, *right);
++left;
--right;
}
性能与兼容性:别为“快”绕开标准库
有人试图用 memcpy 或位运算(如异或交换)提速,但实际毫无必要,反而引入风险:
- 异或交换(
a ^= b; b ^= a; a ^= b;)不适用于同一地址(如swap(arr[i], arr[i])),会导致值清零 -
memcpy需要额外内存空间,违背“原地”需求,且对非 POD 类型(含构造函数/析构函数的对象)行为未定义 -
std::swap和std::reverse在 C++11 及以后对移动语义友好,对std::string、std::vector等类型是移动而非拷贝,效率更高
真正影响性能的通常是缓存局部性——连续内存访问本身很快,而折腾奇技淫巧只会让代码难维护、编译器难优化。
最容易被忽略的是:数组长度为 0 或 1 时,所有方案都应安全退出,无需特殊处理——只要循环条件写对,std::swap 和 std::reverse 天然满足这点。


















