C++ 类 传值 和 传引用 的区别
传参时通过 值传递 和 引用传递 类变量的区别,以及临时变量 直接赋值 和 引用赋值 的区别。
使用引用的方法可以减少拷贝构造函数的调用次数,节省内存资源。
测试代码:
#include <iostream>
using namespace std;
class A{
public:
int val;
A(){
cout << "默认构造函数" << endl;
}
A(int v) : val(v){
cout << "重载构造函数" << endl;
}
A(A& b){
val = b.val;
cout << "拷贝构造函数" << endl;
}
};
void fun1(A a){
cout << "fun1 -- 值传递 -- 临时变量未用引用 &" << endl;
cout << "a address: " << &a << endl;
A b = a;
cout << "b address: " << &b << endl;
b.val = 1;
cout << b.val << endl;
}
void fun2(A a){
cout << "fun2 -- 值传递 -- 临时变量使用引用 &" << endl;
cout << "a address: " << &a << endl;
A& b = a;
cout << "b address: " << &b << endl;
b.val = 2;
cout << b.val << endl;
}
void fun3(A& a){
cout << "fun3 -- 引用传递 -- 临时变量未用引用 &" << endl;
cout << "a address: " << &a << endl;
A b = a;
cout << "b address: " << &b << endl;
b.val = 3;
cout << b.val << endl;
}
void fun4(A& a){
cout << "fun4 -- 引用传递 -- 临时变量使用引用 &" << endl;
cout << "a address: " << &a << endl;
A& b = a;
cout << "b address: " << &b << endl;
b.val = 4;
cout << b.val << endl;
}
int main()
{
A test(0);
cout << "test address: " << &test << endl << endl;
fun1(test);
cout << "test.val = " << test.val << endl << endl;
fun2(test);
cout << "test.val = " << test.val << endl << endl;
fun3(test);
cout << "test.val = " << test.val << endl << endl;
fun4(test);
cout << "test.val = " << test.val << endl << endl;
return 0;
}
输出:
重载构造函数
test address: 0x61ff04
拷贝构造函数
fun1 -- 值传递 -- 临时变量未用引用 &
a address: 0x61ff08
拷贝构造函数
b address: 0x61fedc
1
test.val = 0
拷贝构造函数
fun2 -- 值传递 -- 临时变量使用引用 &
a address: 0x61ff0c
b address: 0x61ff0c
2
test.val = 0
fun3 -- 引用传递 -- 临时变量未用引用 &
a address: 0x61ff04
拷贝构造函数
b address: 0x61fedc
3
test.val = 0
fun4 -- 引用传递 -- 临时变量使用引用 &
a address: 0x61ff04
b address: 0x61ff04
4
test.val = 4
总结:
函数中对类进行值传递时,会先利用拷贝构造函数创建一个与传入参数相同的临时类变量,类似于执行了 A a(test)
;
然后通过直接赋值 A b = a;
再进行一次拷贝构造函数,创建一个新的类变量b。
而引用传递,则是直接传入参数的地址,减少了一次拷贝构造函数的调用;
同样的,引用赋值也未创建新的类变量,而是直接通过参数地址进行操作。
通过 引用传递参数 和 引用赋值,类似于浅拷贝,都未创建新的类变量,因此在函数中对值的改变将会传递到原变量中。
如果不想让函数修改参数的值,只要把参数声明为 const
常量即可。
void fun4(const A& a){
const A& b = a;
cout << b.val << endl;
}
因此,对于 string、vector 等其他类的传递和调用时,可以通过引用传递的方法减少内存的拷贝。