一、C++ 实现:不用指针交换(引用方式)、用指针交换、传值交换(反面例子)
1. 传值交换(错误示范:无法交换实参)
传值方式下,函数形参是实参的副本 ,函数内交换的是副本,实参不会被修改。
cpp
#include <iostream>
using namespace std;
// 传值交换(无效)
void swapByValue(int a, int b) {
int temp = a;
a = b;
b = temp;
cout << "函数内:a=" << a << ", b=" << b << endl; // 副本交换成功
}
int main() {
int x = 10, y = 20;
cout << "交换前:x=" << x << ", y=" << y << endl;
swapByValue(x, y);
cout << "交换后:x=" << x << ", y=" << y << endl; // 实参未变
return 0;
}
输出:
交换前:x=10, y=20
函数内:a=20, b=10
交换后:x=10, y=20
2. 不用指针:引用交换(有效)
引用是变量的别名,函数形参绑定实参的内存地址,操作引用等价于操作原变量。
cpp
#include <iostream>
using namespace std;
// 引用交换(不用指针)
void swapByRef(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 10, y = 20;
cout << "交换前:x=" << x << ", y=" << y << endl;
swapByRef(x, y); // 直接传变量,无需地址
cout << "交换后:x=" << x << ", y=" << y << endl;
return 0;
}
输出:
交换前:x=10, y=20
交换后:x=20, y=10
3. 用指针:地址交换(有效)
指针存储变量的内存地址 ,通过解引用(*)访问地址指向的变量,从而修改实参。
cpp
#include <iostream>
using namespace std;
// 指针交换
void swapByPtr(int *a, int *b) {
int temp = *a; // 解引用:取a地址指向的值
*a = *b; // 把b地址的值赋给a地址
*b = temp; // 把temp赋给b地址
}
int main() {
int x = 10, y = 20;
cout << "交换前:x=" << x << ", y=" << y << endl;
swapByPtr(&x, &y); // 传变量地址(&符号)
cout << "交换后:x=" << x << ", y=" << y << endl;
return 0;
}
输出:
交换前:x=10, y=20
交换后:x=20, y=10
二、用指针与不用指针(引用)的区别与联系
1. 区别
| 维度 | 用指针(swapByPtr) | 不用指针(swapByRef) |
|---|---|---|
| 参数类型 | int*(地址类型) |
int&(引用类型) |
| 传参方式 | 传变量地址(&x, &y) |
直接传变量(x, y) |
| 访问变量 | 需解引用(*a) |
直接用变量名(a) |
| 空值支持 | 可指向空(nullptr) |
必须绑定有效变量,不可为空 |
| 重定向能力 | 可重新赋值指向其他变量(a = &z) |
一旦绑定,不可更改指向 |
| 语法复杂度 | 需处理地址和解引用,稍繁琐 | 语法简洁,接近普通变量操作 |
2. 联系
- 本质都是间接访问:指针通过地址间接访问变量,引用作为别名间接操作原变量,最终都能修改实参(避免传值拷贝的无效性)。
- 底层逻辑相通:引用的底层实现通常由编译器转化为指针(语法糖),二者均基于内存地址操作。
- 效率一致:都无需拷贝变量副本,仅传递地址 / 别名,性能开销极小。
- 功能等价:均可实现 "交换两个数" 的核心需求(传值方式无法实现)。
总结
- 传值交换因拷贝副本无法修改实参,仅用在无需修改原变量的场景。
- 引用是 "语法糖",比指针更简洁安全;指针更灵活(可空、可重定向),但需注意空指针风险。
- 二者核心都是通过内存地址间接操作变量,实现对实参的修改。