来源:
https://www.ctolib.com/docs//sfile/effective-cpp/22.html
对于类型传参,尤其是面向对象特征的语言,有这样几个特征需要注意:
1、子类对象 has a 父类对象(如果接收参数为父类,实参为子类,会存在子类对象部分信息丢失);
2、自定义对象(Class/Struct)的传值会调用拷贝构造/构造函数;
对于自定义类型建议传引用
传引用可避免创建很多临时对象,减少不必要的开销(参考注意事项2);
传引用方式避免切断问题(参考注意事项1);
注意:传引用需考虑是否加const
对于内建类型,建议传值
内建类型的属于C++的C子语言特征,所以传值方式通常比传引用方式更有效;
STL的迭代器和仿函数使用的是C子语言特征(模拟指针的行为),所以通常也是传值更好;
分析:
从编译器层面来看,引用是通过指针来实现的,传引用实际上是传一个指针。
所以,对于内建类型来说(比如int,short),通常传值比传引用高效(比如:32位系统指针占用4个字节,但short只占用2个字节),对于STL的迭代器和仿函数来说同样适用。
传值和传引用不不是根据对象的大小来决定的,编译器对于内建类型和用户自定义类型并不是一视同仁的。
例如,一些编译器拒绝将仅由一个 double 组成的对象放入一个寄存器中,即使在常规上它们非常愿意将一个纯粹的 double 放入那里。如果发生了这种事情,你以传引用方式传递这样的对象更好一些,因为编译器理所当然会将一个指针(引用的实现)放入寄存器。
另一个原因是,小的自定义类型的大小是可以改变的,且随着后面的改变,而导致调用构造/拷贝构造的资源消耗产生很大的变化。以string为例,实现方式有很多,效率也差别很大。