c++ swap函数用法_c++交换两个变量的值

12次阅读

std::swap是c++标准库中高效交换对象值的函数,定义在中,优先使用移动语义或位交换,避免深拷贝;直接赋值会导致数据丢失,手写临时变量冗余且不通用。

c++ swap函数用法_c++交换两个变量的值

std::swap 是什么,为什么不能直接用赋值

std::swap 是 C++ 标准库中用于交换两个对象值的函数,定义在 头文件里。它不是简单的三行赋值(临时变量 + a=b + b=临时),而是针对不同类型做了优化:对基础类型是位交换,对类类型会优先调用移动语义(如果可用),避免深拷贝开销。

直接写 a = b; b = a; 会导致 b 值丢失,这是初学者常见错误;而手写临时变量虽然可行,但冗余、易错,且无法自动适配自定义类型或容器。

基本用法:交换 intdoubleString 等内置/标准类型

只要类型支持移动构造/赋值或拷贝构造/赋值,std::swap 就能用。注意必须显式包含头文件,否则编译报错 ‘swap’ was not declared in this scope

  • 不加 using std::swap; 时,必须写全名 std::swap(a, b)
  • std::Arraystd::vector 等容器,std::swap 会交换内部指针(O(1) 时间),而不是逐个元素复制
  • 交换 const 对象?不行 —— std::swap 参数是左值引用,要求可修改
#include  #include  

int main() { int a = 10, b = 20; std::swap(a, b); // ✅ 安全、高效 std::cout << a << " " << b << "n"; // 输出: 20 10 }

自定义类怎么让 swap 更快:提供非成员 swap 重载

如果你的类管理动态资源(比如自己 new 的数组),默认的 std::swap 会触发拷贝构造 + 拷贝赋值,性能差还可能抛异常。正确做法是在类所在命名空间中定义非成员 swap 函数,并声明为 friend 或公有接口

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

  • 不要在 std 命名空间里加东西(违反标准,未定义行为)
  • ADL(参数依赖查找)会让 std::swap(x, y) 自动找到你定义的 swap(MyClass&, MyClass&)
  • 函数体内应只做成员交换(用 std::swap 递归交换各字段),不分配新资源
struct Widget {     int* data;     Widget(int x) : data(new int(x)) {}     ~Widget() { delete data; }     // ... 拷贝/移动操作略 }; 

// 在 Widget 同一命名空间(全局)中定义 void swap(Widget& a, Widget& b) noexcept { std::swap(a.data, b.data); // 仅交换指针 }

常见陷阱:std::swap 与 ADL 冲突、右值引用误用

最隐蔽的问题是:你写了自定义 swap,但调用时没触发,还是走默认拷贝版。原因常是忘记 ADL 触发条件 —— 比如用了 using std::swap; 后又写 swap(a, b),编译器可能只找 std::swap 而忽略你的版本。

  • 安全写法:始终用 using std::swap; swap(a, b);(两行),靠 ADL 找到最优重载
  • 别对字面量或临时对象调用 std::swap:例如 std::swap(1, x) 编译失败(无法绑定非常量左值引用)
  • 容器的 swap 成员函数(如 v1.swap(v2))和 std::swap(v1, v2) 等价,但前者更明确,某些老编译器对后者 ADL 支持弱

真正复杂的地方在于:当类模板嵌套、继承关系存在时,swap 重载要覆盖所有可能组合,稍有遗漏就退化成低效拷贝 —— 这点很容易被忽略,直到压测时发现内存暴涨或卡顿。

text=ZqhQzanResources