C++中RAM内的小对象:传值是否比传引用更高效?
普遍认知里说C++传引用比传值更优,核心是觉得能减少拷贝次数,但这个结论不是放之四海而皆准的,尤其是针对你提到的场景——对象在RAM而非缓存中,且函数要多次访问其字段,不超过128字节的小对象确实有可能传值更高效,具体分析如下:
传值的缓存收益:当对象在RAM中时,传值会一次性把整个对象(≤128字节)拷贝到函数栈空间(通常属于处理器缓存范围,或者能快速被加载到缓存)。后续函数访问对象字段时,都是直接在缓存内操作,完全避免了多次RAM寻址的高昂成本。毕竟每次通过引用访问字段,都要先解引用指针定位到RAM中的对象,单次RAM访问就要200-600周期;而一次性拷贝64-128字节的成本仅需几十周期,远低于多次RAM访问的总开销。
编译器的隐式优化局限:编译器确实会做各种优化,但没法在所有场景下自动完成你说的“隐式缓存拷贝”。比如如果函数是外部链接(不在当前编译单元),编译器看不到函数内部的访问逻辑,就没法判断是否需要把引用对象缓存到栈上。只有当函数是内联的、且编译器能获取完整函数体时,才有可能将引用访问优化为类似传值的缓存访问,但这不是必然发生的。
实际场景的边界条件:128字节是个参考值,本质上对应常见处理器的缓存行大小(64或128字节),如果对象大小刚好匹配缓存行,传值的拷贝成本最低。另外还要看函数内部对字段的访问频率:如果只访问1-2次,传引用的开销可能更低;但如果是频繁访问,传值的缓存收益就会非常明显。
额外注意点:如果对象是带自定义拷贝逻辑的非POD类型(比如有深拷贝的类),哪怕对象体积小,传值的拷贝成本也会急剧上升,这时候还是传引用更划算。只有当对象是简单POD类型(比如普通结构体)时,传值的拷贝成本才可以忽略不计。
内容的提问来源于stack exchange,提问作者Dmitriy Sitnikov

