C++中(&object)->something与object.something的优劣及优化疑问
聊聊
(&object)->something和object.something的那些事儿 嘿,这个问题问得挺到位的,刚好我之前也琢磨过类似的写法,给你好好唠唠~
1. 这种写法相较于object.something有优势吗?
功能上,这俩完全等价——(&object)->something本质上就是先取对象的地址,再通过指针箭头访问成员,而object.something是直接访问对象成员,展开来看(&object)->something等于(*(&object)).something,最终就是object.something。
那为啥有人会写前者?大概率是这两种场景:
- 个人编码习惯:有些开发者平时写多了指针操作,对
->的手感比对.更熟,处理栈上对象的时候顺手就敲了(&obj)->,没别的特殊理由,纯个人风格偏好。 - 宏定义兼容需求:在一些通用宏里,为了让宏尽量统一语法(减少分支判断),会用取地址+箭头的写法兼容对象实例的传入。比如写一个打印结构体成员的宏:
这种情况下,传入栈上的#define PRINT_PERSON_NAME(p) printf("%s\n", (&(p))->name)struct Person p时宏能正常工作;不过要是传入指针struct Person *p就会出问题(变成二级指针访问),所以正经的兼容宏会加额外判断,但核心思路是用这种写法来统一语法逻辑。
除此之外,这种写法没有任何功能上的优势,反而会让代码可读性打折扣——毕竟大家默认用.访问对象成员,用->访问指针,突然冒出来(&obj)->会让其他开发者愣一下:“为啥要多此一举?”
2. 编译器会优化这类代码吗?性能上有优势吗?
结论很明确:编译器会完全消除两者的差异,性能上没有任何区别。
因为(&object)->something是语法层面的等价转换,编译器在前端语法分析阶段就会把它转换成和object.something完全一样的中间表示,最终生成的机器码是一模一样的。你甚至可以自己验证:用GCC或Clang编译代码时加上-S参数生成汇编,对比两种写法的汇编输出,会发现完全没差别。
说白了,这种写法就是个“语法糖的反向操作”,完全不涉及性能差异,纯粹是写法上的选择。
内容的提问来源于stack exchange,提问作者Daniel D.
相关产品推荐
相关产品推荐

