C++中值传递和引用传递的区别
C++中值传递和引用传递的区别
值传递:在函数调用时,传递的是实际参数的副本,因此函数内对参数的修改不会影响到实际参数。
引用传递:在函数调用时,传递的是实际参数的引用,因此函数内对参数的修改会影响到实际参数。
值传递
示例代码:
class A{
public:
A() {
std::cout << "A constructor called" << std::endl;
}
A(const A& other) {
std::cout << "A copy constructor called" << std::endl;
}
int a;
};
void func(A a) {
a.a = 20;
}
int main() {
A a;
a.a = 10;
std::cout << "before func call, a.a = " << a.a << std::endl;
func(a);
std::cout << "after func call, a.a = " << a.a << std::endl;
return 0;
}
输出结果:
//传递的是副本,因此调用了拷贝构造,修改了副本,不会影响到实际参数
A constructor called
before func call, a.a = 10
A copy constructor called //调用拷贝构造
after func call, a.a = 10
引用传递
示例代码:
class A{
public:
A() {
std::cout << "A constructor called" << std::endl;
}
A(const A& other) {
std::cout << "A copy constructor called" << std::endl;
}
int a;
};
void func(A& a) {
a.a = 20;
}
int main() {
A a;
a.a = 10;
std::cout << "before func call, a.a = " << a.a << std::endl;
func(a);
std::cout << "after func call, a.a = " << a.a << std::endl;
return 0;
}
输出结果:
//传递的是引用,因此不会调用拷贝构造,直接修改了实际参数
A constructor called
before func call, a.a = 10
after func call, a.a = 20
使用场景
从机制上来看,值传递适用于不可变的对象,即你不希望改变原本对象的值,而引用传递适用于可变的对象,即你希望改变原本对象的值。
从性能上考虑,值传递需要拷贝对象,对于简单数据类型,两者区别较小,但对于类、结构体等复杂对象,拷贝过程可能比较耗时,而引用传递不需要拷贝对象,因此在性能上有优势。在使用上应尽可能使用引用传递来减少拷贝的开销。如果你不希望改变原本对象可以通过添加const关键字来实现
拓展
引用可以理解为一个对象的别名(底层应该是通过指针常量实现的,这个博主不太确定),因此引用在初始化时就必须绑定(先有对象存在,才能给对象起别名),而且绑定之后不能再改变。
示例代码:
class A{
public:
A() {
std::cout << "A constructor called" << std::endl;
}
A(const A& other) {
std::cout << "A copy constructor called" << std::endl;
}
A& operator=(const A& other) {
std::cout << "A copy assignment operator called" << std::endl;
return *this;
}
int a;
};
void func(A& a) {
A b;
b.a = 20;
A& ref_b = b;
//一样的效果
a = ref_b;
//a = static_cast<A&>(ref_b);
std::cout << "func ptr a = " << &a << std::endl;
std::cout << "func ptr b = " << &b << std::endl;
}
int main() {
A a;
a.a = 10;
std::cout << "main ptr a = " << &a << std::endl;
std::cout << "before func call, a.a = " << a.a << std::endl;
func(a);
std::cout << "after func call, a.a = " << a.a << std::endl;
return 0;
}
输出结果:
//地址不一致,实际调用的是赋值运算符
A constructor called
main ptr a = 0000007B772FFC14
before func call, a.a = 10
A constructor called
A copy assignment operator called
func ptr a = 0000007B772FFC14
func ptr b = 0000007B772FFAD4
after func call, a.a = 10
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了