尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

const 类名 rp 形参深度理解

const 类名 rp 形参深度理解 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构造对象:nameendl;}Person::Person(const Personother){nameother.name;cout执行拷贝构造生成副本endl;}void func_value(Person p){coutfunc_value 内部 p.name p.nameendl;}void func_const_ref(const Personp){coutfunc_const_ref 内部 p.name p.nameendl;// p.namexxx;// ?编译报错const引用不能修改p的成员}int main{Person ps(tom);func_value(ps);func_const_ref(ps);return0}输出构造对象:tom执行拷贝构造生成副本func_value 内部 p.name tomfunc_const_ref 内部 p.name tomfunc_ref (Person (“临时对象”) ) 为啥说传入的是临时变量什么是临时变量什么是临时对象临时变量func_ref( Person(“临时对象”) );Person(“临时对象”) 这一整句没有名字、没有变量名、写在函数实参位置用完马上销毁这就是临时对象右值。普通对象左值有名字Person p(“jack”); // p 是具名变量有变量名p存在栈上func_ref ( p ); // 传变量pp还活着后续代码还可以继续用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; // ab运算结果产生临时对象再拷贝给c.关键语句执行时序func_ref( Person(“临时对象”) );执行步骤调用构造函数创建Person(“临时对象”)→临时对象没有名字把这个临时对象传给函数参数函数调用结束分号 ;这整条语句执行完毕临时对象马上调用析构销毁。回到之前的语法问题为什么 void func_ref(Person rp) 不能接收临时对象void func_ref(Personrp){}func_ref(Person(临时对象));// ❌编译报错C 设计规则非 const 左值引用 T不能绑定临时对象为什么要有这个规则设计初衷假设语法允许写void func_ref(Personrp){rp.name修改名字;// 企图修改传入的对象}func_ref(Person(临时对象));传入的是临时对象函数执行完这条语句结束临时对象马上销毁。你在函数内部修改了 rp但是外面没有任何变量能看到这个修改修改完全没有意义属于逻辑 bug。C 直接在编译层面阻止这件事不让临时对象绑定到普通引用T防止你做无意义的修改。那为什么 const Person rp 就可以绑定临时对象void func_const_ref(const Personrp){}func_const_ref(Person(临时对象));// ✅允许const代表函数内不能修改 rp 对象。既然不让修改就不会出现上面那种 “修改临时对象结果直接销毁丢失” 的 bugC 允许这种绑定。额外特性当临时对象绑定到const T引用参数的时候临时对象生命周期被延长直到函数结束才销毁而不是语句分号立刻销毁。区分左值 / 右值通俗记忆左值有名字、有持久生命周期可以取地址能放在赋值号左边。Person p; p xxx; → p 是左值。右值临时对象没有名字用完就要销毁不能放在赋值号左边。Person(“abc”)、函数返回临时值都是右值。
返回列表