写在前面,题主问的是内置类型,那么,基本上就是int char long ptr这类数据,我的回答基于这个大前提来讨论,所以不要再提什么构造函数之类的内容了。
引用和按指针传递,在汇编级别上应该是一样的,所以你的代码里f2和f3在汇编层面上应该是一样的,所以性能上应该没有差别。
至于值传递和引用传递的性能差别,我觉得不应该是写C++代码该关注的地方。
如果真要深入分析这个问题,在不开任何优化的情况下:
mov和lea指令速度是有可能有差异的,现代的x86架构的CPU里,开启流水线不开启HT的情况下,lea可能比mov要快,或者基本上差不多,我查到的信息里:
Ryzen架构下:
MOV r,m的latency是3,throughput是1/2;
LEA r32/64,[m]的latency是2,throughput是1/4;
Haswell架构下:
MOV r32/64,m的latency是2,throughput是1/2;
LEA r32/64,m的latency是1,throughput是1/2;
整体上LEA是要快一些的。
但这里只是考虑到调用者的情况,如果是传引用或者指针,那么意味着被调用函数的内部需要做地址转换,才能获得实际的参数的值。
对于32位系统来说,参数是在栈上的,要先通过ebp获得参数值(指针或者引用),再通过参数值获得实际的指向或者引用的值,要进行两次取地址的操作。
对于64位系统来说,参数是通过寄存器来传递的,仍然需要一次取地址操作才能获得实际的值。
而如果是值传递的话,就没那么复杂了,参数就在栈上甚至在寄存器里,直接用就可以。因此整体来看,如果按值传递,被调用者的开销确实更小。
所以,大致的结论是:对于内置类型来说,值传递确实比指针(和引用)效率要高
以上只是不开优化的结论,开优化以后,性能就不好说了,而且代码的复杂度也会影响优化的效果。
虽然结论是值传递更快,但我仍然觉得如果没有特别的需求,写代码的人不太建议关注它。
-------------------------
更进一步的思考一下:用值传递,那么肯定是不关注这个参数在被调函数内的变化,而用指针或者引用,那么一定是关注这种变化,两种方式的用途是不一样的,效率上有差异是必然的,但多数情况下,不需要人为的去优化,编译器的优化已经足够用了。