C++ 怎么交换两个变量 C++ swap函数与位运算交换法【技巧】

2次阅读

应直接使用 std::swap,它针对内置类型内联优化、对类类型自动调用移动语义、支持ADL;手写异或交换可读性差、同地址时归零、无法并行且不适用于浮点/结构体

C++ 怎么交换两个变量 C++ swap函数与位运算交换法【技巧】

直接用 std::swap,别手写位运算

绝大多数情况下,std::swap 是最优解。它被深度优化过:对内置类型(如 intdouble)通常内联为几条汇编指令;对类类型会自动调用移动语义(c++11 起),避免深拷贝;还支持 ADL(参数依赖查找),能正确调用用户自定义的 swap 函数。

手写位运算(如异或交换)不仅可读性差,还容易出错——比如两个变量指向同一内存地址时,a ^= b; b ^= a; a ^= b; 会让值变成 0。

使用方式很简单:

#include  // C++11 起,std::swap 在  中 int a = 1, b = 2; std::swap(a, b); // 直接交换,安全、高效、通用

什么时候不能用 std::swap?其实基本没有

有人以为“嵌入式环境没 STL”或“怕模板膨胀”,但现代嵌入式工具链(如 ARM GCC + libc++ 或 minimal STL 实现)都支持 std::swap 的轻量版本。真正受限的场景极少,例如:裸机启动早期、寄存器级编程、或某些极端资源约束的微控制器(无标准库)。

立即学习C++免费学习笔记(深入)”;

即便如此,也建议优先用编译器内置函数(如 __builtin_swap32)或明确的临时变量,而不是位运算:

  • std::swapvolatile 变量无效(会触发未定义行为),此时必须用临时变量
  • 交换非 trivial 类型(含虚函数、引用成员等)时,std::swap 仍可用,但底层依赖其拷贝/移动构造函数是否可用
  • 若类型未定义移动操作且拷贝代价极高,应先检查能否改用移动语义,而非退化到位运算

异或交换法的问题不止是“同地址变零”

异或交换(a ^= b; b ^= a; a ^= b;)表面省空间,实际在现代 CPU 上反而更慢:它强制串行执行(第二步依赖第一步结果),无法被指令流水线并行;而 std::swap 用临时变量的三指令通常能乱序执行。

其他硬伤包括:

  • 只适用于整型指针(浮点数、结构体不支持 ^
  • 无法用于 const 或引用绑定的变量(const int& a = x; 不可修改)
  • 编译器很难对其优化——甚至可能因别名分析失败而禁用某些优化
  • 调试时难以跟踪:三个语句逻辑耦合,断点打断后中间状态无意义

真要手写交换,就用临时变量,别炫技

如果因某种原因不能用 std::swap(比如教学演示、极简环境),最稳妥的做法就是显式临时变量:

int temp = a; a = b; b = temp;

它语义清晰、无副作用、兼容所有可赋值类型、编译器能轻松优化成寄存器交换。相比位运算,多一行代码,少十个 bug

真正需要关注的不是“怎么交换”,而是“为什么需要交换”——比如是否本该用 std::sort 的谓词、是否误用了需手动交换的算法结构、或者是否该用 std::tuple / 结构化绑定替代多次单变量交换。

text=ZqhQzanResources