C++の传值、传址与传引用
1. 概念
2. 简单例子
代码如下:
#include <iostream>
using namespace std;
void swapValue(int a, int b){
int temp = a;
a = b;
b = temp;
}
void swapRef(int &a, int &b){
int temp = a;
a = b;
b = temp;
}
void swapPtr(int *a, int *b){
int temp = *a;
*a = *b;
*b = temp;
}
int main(){
int a = 1;
int b = 4;
cout << "Original Status: " << endl;
cout << "a = " << a << "\t" << "b = " << b << "\t" << "&a = " << &a <<"\t" <<"&b = " << &b << endl;
swapValue(a, b);
cout << "After passing by value :" << endl;
cout << "a = " << a << "\t" << "b = " << b << "\t" << "&a = " << &a <<"\t" <<"&b = " << &b << endl;
swapRef(a, b);
cout << "After passing by ref: " << endl;
cout << "a = " << a << "\t" << "b = " << b << "\t" << "&a = " << &a <<"\t" <<"&b = " << &b << endl;
swapPtr(&a, &b); //这里会恢复原值,因为上面引用已经交换过了。
cout << "After passing by Ptr: " <<endl;
cout << "a = " << a << "\t" << "b = " << b << "\t" << "&a = " << &a <<"\t" <<"&b = " << &b << endl;
return 0;
}
运行后,结果如下:
Original Status:
After passing by value :
a = 1 b = 4 &a = 0x61fe1c &b = 0x61fe18
After passing by ref:
a = 4 b = 1 &a = 0x61fe1c &b = 0x61fe18
After passing by Ptr: //注意这里貌似是没有通过指针交换,实际上是因为上面的引用已经换过了,传指针又将其恢复了。
a = 1 b = 4 &a = 0x61fe1c &b = 0x61fe18
3. 三种方式比较
-
功能上:传值不可以在主调函数中改变实参;传指针与传引用则可以在主调函数中改变实参的值。而且,指针是最灵活的。
-
传递效率上:指主调函数中实参传递到被调函数中的形参中的效率。对于32位的机器,小于4字节的参数,可以看出是值传递效率更高,要是大于4字节参数或者自定义的数据类型(class、struct),最好就是使用传址或者传引用。
-
执行效率上:指在被调函数体内执行的效率。传值的话就是直接寻址,指针与大部分情况下的引用则是通过间接寻址的方式执行的。所以传值执行效率稍高些。对于传过来的变量的频繁操作且总次数很多的情况下,传址和传引用有较多的效率损失。
综合2和3来看,传引用效率始终是不低于传指针的。所以C++优先传引用而非指针。😙
-
“Reference when possible, Pointers when needed!”
4. 一个可能忽视的点
考虑如下代码:
int add(int a, int b){
return a + b;
}
int main(){
int m = 0, n = 1;
int ret = add(m, n);
return 0;
}
实参m、n值传递给被调函数add,进行相应计算。但是我们不需要修改实参,我们想要的就只是一个返回值,所以在6行,程序开始运行add子程序,执行完之后,还是在第6行继续进行,将add函数返回值赋值给ret。
这个例子是不让自己混淆 上面讨论的修改实参问题 与 直接拷贝返回值。