我认为这个问题本身存在很大的误解。
一方面堆栈或堆分配的对象与另一方面通过值或引用或指针传递之间没有关系。
堆栈与堆分配
尽可能选择堆栈,然后为您管理对象的生命周期,这更容易处理。
但在以下几种情况下可能是不可能的:
- 虚拟建筑(想想工厂)
- 共享所有权(尽管您应该始终尽量避免它)
我可能会错过一些,但在这种情况下,您应该使用 SBRM(范围绑定资源管理)来利用堆栈生命周期管理功能,例如通过使用智能指针。
传递:值、引用、指针
首先,语义上有区别:
- value, const reference:传递的对象不会被方法修改
- 参考:传递的对象可能被方法修改
- 指针/常量指针:与引用相同(对于行为),但可能为空
请注意,某些语言(像 Haskell 之类的函数式语言)默认不提供引用/指针。一旦创建,这些值就是不可变的。除了一些处理外部环境的变通方法之外,它们不受这种使用的限制,并且它以某种方式使调试更容易。
你的朋友应该知道,pass-by-reference 或 pass-by-pointer 绝对没有错:例如 thing of swap
,它不能用 pass-by-value 来实现。
最后,多态性不允许按值传递语义。
现在,让我们谈谈表演。
通常人们普遍认为内置函数应该通过值传递(以避免间接),而用户定义的大类应该通过引用/指针传递(以避免复制)。big实际上通常意味着复制构造函数不是微不足道的。
然而,关于小型用户定义的类有一个悬而未决的问题。最近发表的一些文章表明,在某些情况下,按值传递可能允许编译器进行更好的优化,例如,在这种情况下:
Object foo(Object d) { d.bar(); return d; }
int main(int argc, char* argv[])
{
Object o;
o = foo(o);
return 0;
}
在这里,智能编译器能够确定o
可以在不进行任何复制的情况下就地修改!(我认为函数定义必须是可见的,我不知道链接时间优化是否会解决这个问题)
因此,与往常一样,性能问题只有一种可能性:measure。