显式解引用指针以引用传递时编译器层面的行为探究
显式解引用指针并传引用给函数时的编译器行为分析
先看第一个代码片段的行为:
void foo(A& arg) { arg.member = 7; } void goo() { A* ob = new A(); foo(*ob); printf(ob->member); // 应该输出7 }
对指针ob执行解引用操作*ob后,得到的是堆上A对象的左值。当把这个值传给接受A&类型参数的foo函数时,函数形参arg会直接绑定到堆上的原对象。因此在foo中修改arg.member,本质就是直接修改原对象的成员变量,最后通过ob->member访问时,自然会得到修改后的7。
再看第二个代码片段,两者的核心差异出现在解引用的时机和用途上:
void foo(A& arg) { arg.member = 7; } void goo() { A* ob = new A(); A ob_dereferenced = *ob; foo(ob_dereferenced); printf(ob->member); // 应该输出A初始化member的默认值 }
这里A ob_dereferenced = *ob;并不是创建原对象的引用,而是通过拷贝构造函数创建了一个全新的栈上对象,这个对象是堆上原对象的副本。之后调用foo(ob_dereferenced)时,形参arg绑定的是这个栈上的副本,所有修改操作都只作用于副本,堆上的原对象完全不受影响。所以最后printf输出的还是原对象初始化时的member值。
总结两者的核心区别:
- 直接传
*ob给foo:解引用结果直接作为引用绑定到原对象,操作的是原对象本身 - 先赋值给
ob_dereferenced再传参:解引用触发拷贝构造,生成独立副本,后续操作与原对象无关
内容的提问来源于stack exchange,提问作者Omroth
相关产品推荐
相关产品推荐

