应始终使用 std::swap,它安全高效且自动适配类型;手写无临时变量交换(如 a ^= b ^= a ^= b)是未定义行为,整数溢出、浮点精度、求值顺序均导致不可预测结果。

直接用 std::swap 是最安全的选择
绝大多数情况下,别手写交换逻辑,直接调用 std::swap。它针对内置类型做了优化,对自定义类型会自动调用移动语义(C++11 起),还能正确处理引用、数组、容器等边界情况。
常见错误是自己写临时变量交换,比如:int t = a; a = b; b = t;——这在 a 和 b 是同一变量(如 swap(arr[i], arr[i]))时看似无害,但一旦涉及类类型或带副作用的表达式(比如 swap(*ptr++, *ptr++)),就可能出未定义行为。
-
std::swap在<utility></utility>头文件中,C++11 及以后无需额外操作 - 对
int、double等基本类型,编译器通常内联为几条汇编指令,性能无损 - 如果交换的是大对象(如
std::vector),std::swap会调用其特化版本,只交换内部指针,不拷贝数据
什么时候不能用 std::swap?
极少场景下需要绕过 std::swap:比如两个变量是同一内存地址且类型不支持自赋值(极少见),或你在写底层库、调试内存布局、或必须避免依赖标准库(嵌入式裸机环境)。
此时可考虑 std::memcpy + 临时缓冲区,但必须确保类型是 trivially_copyable;或者用 std::bit_cast(C++20),但兼容性差。手写 XOR 交换(a ^= b ^= a ^= b)仅适用于整数,且在 a 和 b 相同时结果为 0,已完全不推荐。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- XOR 交换在
a == b时失效,且无法用于浮点、指针、类类型 -
std::memcpy方案需手动管理对齐和大小,容易因sizeof(T)误判而出错 - 任何手写方案都无法自动适配 move-only 类型(如
std::unique_ptr)
模板参数推导失败?检查是否忘了 using std::swap;
当对自定义类型调用 swap 时,如果没提供 swap 的重载,ADL(参数依赖查找)可能找不到函数,导致编译错误,例如:error: no matching function for call to 'swap(MyClass&, MyClass&)'。
标准做法是在调用处写 using std::swap;,再调用无限定名的 swap(a, b)。这样既能触发 ADL 找到用户定义的 swap 特化,又能回落到 std::swap 默认实现。
- 不要直接写
std::swap(a, b)—— 这会跳过用户自定义的更高效特化 - 自定义类型应提供非成员
swap函数(通常在类同命名空间内),并标记为noexcept - 如果类型支持移动构造/赋值,
std::swap默认实现已足够好,无需手动特化
宏 #define swap(a,b) 是危险的遗产
老代码里偶尔能看到用宏实现的 swap,比如 #define swap(a,b) { auto t=a; a=b; b=t; }。这种写法在 C++ 中几乎总是错的:无法处理不同类型、引发多次求值(swap(*p++, *q++) 会自增两次)、作用域污染、与标准库冲突。
- 宏没有类型检查,
swap(3.14, 42)可能静默截断 - 宏展开后变量名
t可能与外层变量重名,引发未定义行为 - C++11 后所有主流编译器都支持
std::swap的完美转发,宏毫无优势
真遇到必须用宏的极端场景(比如跨 C/C++ 兼容头),也应加唯一前缀(如 MY_SWAP)并严格限制作用域。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










