不使用临时变量的swap再思考 -- 六种解法

本文探讨了不使用临时变量进行swap操作的六种方法,包括乘除法和位运算。这些方法在特定情况下,如浮点数,可能适用。需要注意的是,当a等于b时,某些方法可能会失效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不使用临时变量的swap



一道经典的面试题如下:两个int型变量a和b,不使用临时变量,交换它们的值。
答案相信大家都耳熟能详了:
a = a ^ b;
b = a ^ b;
a = a ^ b;

这段程序巧妙的安排运算顺序利用仅有的两个变量实现swap,它相当于这样一段程序:
c = a ^ b;
b = c ^ b;
a = c ^ b;

可以发现它的技巧简单的说就是把本应放在临时变量c中的值放在了原有变量a中,a的值被覆盖。不过为什么a的值可以被覆盖掉呢?对这段程序一种比较technical的解释就是,它利用了 ^ (异或)运算的性质:
c = a ^ b  =>
   a = b ^ c
   b = a ^ c

但是,大家怎么想起来使用异或呢?使用异或有什么好处呢?两个变量既然要交换,那总归是要赋值的,而在C语言中有不能像Python那样直接一句搞定:
a , b = b , a

所以有这么一个结论:两个变量的最终赋值肯定是有先后顺序的。设a、b的初始值为A、B。假设b先完成赋值,即b已经存储了a的初始值A,现在要把b的初始值B放到a里面去。这时候可用的变量只有a了。也就是说在b完成赋值之后,a一定要包含b的初始值信息B,这样就或可能由a和b得到B,那么a一定包括A和B的信息。这里就是信息论的一点应用了。

可能的解


在C/C++语言中,怎么做运算才能保证把把两段信息放到一个变量中,知道一段信息后就可以分离出另一段信息呢?
最容易想到的运算可能是位运算。
C语言中的按位逻辑运算有这四种:
&:与,仅在两个operand均为1时为1
|:或,仅在
<< `std::swap` 是 C++ 标准库提供的一种用于交换两个变量值的通用算法。 **一、使用方法** 1. **基本数据类型** 对于基本的数据类型(如 int, double等),可以直接调用 `std::swap` 函数进行交换操作: ```cpp int a = 5; int b = 10; std :: swap(a,b); //此时a=10;b=5; ``` 2. **自定义类型的swap重载** 如果想要为自己的类或结构体也能够方便地使用 `std::swap` 进行成员属性之间的互换,则可以通过全局函数或者类内非静态成员函数的形式对该函数进行重载。通常来说,在 STL 容器中插入 自定义 类型 的对象时,编译器会自动选择合适的版本;但为了确保效率与正确性,我们还是建议用户自己去明确指定如何执行“元素间”内容上的替换行为。 例如以下这个简单的Person类的例子: ```cpp class Person { public: string name; int age; private : //... }; void swap(Person& first , Person & second){ using std::swap; //引入命名空间中的模板化版本作为默认回退选项 swap(first.name ,second.name ); swap( first.age , second.age); } ``` 以上代码展示了怎样为包含字符串和其他内置数值字段的人类实体编写辅助工具程序以支持其内部状态信息间的相互转移功能. **二、原理及实现机制** 实际上在很多标准库里边它的底层逻辑大概是这样的 : - 创建临时副本 : 先把第一个参数所指代目标的内容复制到局部作用域下的新实例里. - 移动赋值: 接着将第二个实参里的原始资料搬移到原先存放前者的位置上. - 最后一步则是完成反向搬运动作——即让最初传入的那个被当作源端的对象接收下暂存区内的东西. 这样做虽然简单直接但也并非总是最优解法尤其是在处理大型复杂记录结构或是频繁涉及动态内存分配的情形下可能会带来必要的开销因此部分优化后的变种形式采用了更巧妙的设计思路比如只交换指向实际存储地址的引用而非整个对象本体本身从而避免了重复拷贝带来的额外负担。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值