const 类名& rp 形参深度理解
核心记住三件事:
- const ClassA& rp:引用,不传值,不会发生对象拷贝;rp 是实参对象的别名,同一块内存。
- const:通过 rp 不能修改源对象;但源对象本身可以被外面修改。
- const& 既能接收普通左值,也能接收临时对象(右值),这是它和普通 ClassA& rp 最大区别。
对比三个签名:
- 值传递:ClassA rp → 会拷贝,生成新对象
- 非const引用:ClassA& rp → 不拷贝,只能接收左值,不能接临时对象
- const引用:const ClassA& rp → 不拷贝,可读不可改,左值、临时对象都能接。
Person::Person(string n):name(n){cout<<"构造对象:"<<name<<endl;}Person::Person(const Person&other){name=other.name;cout<<"=====执行拷贝构造!生成副本====="<<endl;}void func_value(Person p){cout<<"func_value 内部 p.name = "<<p.name<<endl;}void func_const_ref(const Person&p){cout<<"func_const_ref 内部 p.name = "<<p.name<<endl;// p.name="xxx";// ?编译报错!const引用,不能修改p的成员}int main(){Person ps("tom");func_value(ps);func_const_ref(ps);return0;}输出:
构造对象:tom
=执行拷贝构造!生成副本=
func_value 内部 p.name = tom
func_const_ref 内部 p.name = tom
func_ref (Person (“临时对象”) ) ,为啥说传入的是临时变量,什么是临时变量
什么是临时对象(临时变量)
func_ref( Person(“临时对象”) );
Person(“临时对象”) 这一整句,没有名字、没有变量名、写在函数实参位置,用完马上销毁,这就是临时对象(右值)。
- 普通对象(左值,有名字)
Person p(“jack”); // p 是具名变量,有变量名p,存在栈上;
func_ref ( p ); // 传变量p,p还活着,后续代码还可以继续用p.
p:有名字,可以取地址 &p;生命周期由大括号作用域控制,出大括号才销毁。
👉 左值:可以出现在赋值号左边。p = Person(“xxx”); 合法。
- 临时对象(临时变量,右值,没有名字)
func_ref( Person(“临时对象”) );
Person(“临时对象”):
//
- 没有变量名字,没有标识符接收这个对象;
- 在这一行语句创建;
- 语句结束,立刻就要销毁;
- 你拿不到它的变量名,虽然可以取地址&Person(“xxx”),但生命周期极短。
临时对象不一定只在函数参数出现,下面这些全部都是临时对象:
// 1.函数返回值,临时对象
Person getPerson(){ return Person(“aa”); }
getPerson(); // 返回出来的Person是临时对象
//2.表达式产生临时对象
Person a(“a”),b(“b”);
Person c = a + b; // a+b运算结果产生临时对象,再拷贝给c.
关键:语句执行时序
func_ref( Person(“临时对象”) );
执行步骤:
调用构造函数,创建Person(“临时对象”)→临时对象,没有名字
把这个临时对象传给函数参数
函数调用结束,分号 ;,这整条语句执行完毕,临时对象马上调用析构销毁。
回到之前的语法问题:为什么 void func_ref(Person& rp) 不能接收临时对象?
void func_ref(Person&rp){}func_ref(Person("临时对象"));// ❌编译报错C++ 设计规则:
非 const 左值引用 T&,不能绑定临时对象
为什么要有这个规则?(设计初衷)
假设语法允许写:
void func_ref(Person&rp){rp.name="修改名字";// 企图修改传入的对象}func_ref(Person("临时对象"));传入的是临时对象,函数执行完,这条语句结束,临时对象马上销毁。
你在函数内部修改了 rp,但是外面没有任何变量能看到这个修改,修改完全没有意义,属于逻辑 bug。
C++ 直接在编译层面阻止这件事:不让临时对象绑定到普通引用T&,防止你做无意义的修改。
那为什么 const Person& rp 就可以绑定临时对象?
void func_const_ref(const Person&rp){}func_const_ref(Person("临时对象"));// ✅允许const代表:函数内不能修改 rp 对象。既然不让修改,就不会出现上面那种 “修改临时对象,结果直接销毁丢失” 的 bug,C++ 允许这种绑定。
额外特性:当临时对象绑定到const T&引用参数的时候,临时对象生命周期被延长,直到函数结束才销毁,而不是语句分号立刻销毁。
区分:左值 / 右值通俗记忆
左值:有名字、有持久生命周期,可以取地址;能放在赋值号=左边。
Person p; p = xxx; → p 是左值。
右值:临时对象,没有名字,用完就要销毁;不能放在赋值号左边。
Person(“abc”)、函数返回临时值,都是右值。