Bef*_*rem 17 c++ pass-by-reference pass-by-name
让我们说我认识一个不熟悉C++的人.他没有绕过指针(正确地说是这样),但他拒绝通过引用传递.他总是使用传值.原因是他觉得"通过引用传递物体是一种破碎设计的标志".
该程序是一个小型图形程序,大多数传递的问题是数学Vector(3元组)对象.有一些大的控制器对象,但没有比这复杂.
我发现很难找到一个反对只使用堆栈的杀手论点.
我认为按值传递对于诸如向量之类的小对象是好的,但即使这样,代码中也会发生许多不必要的复制.按值传递大型对象显然是浪费,很可能不是您想要的功能.
在专业方面,我相信堆栈在分配/解除分配内存方面更快,并且具有恒定的分配时间.
我能想到的唯一主要论点是堆栈可能会溢出,但我猜这是不可能发生的?是否有任何其他参数反对仅使用堆栈/传递值而不是通过引用传递?
ste*_*anv 14
Subtyping-polymorphism是一种情况,其中传递值不起作用,因为您将派生类切片到其基类.也许对某些人来说,使用subtyping-polymorphism是不好的设计?
你朋友的问题与他的宗教信仰不同.给定任何函数,总是考虑通过值,引用,const引用,指针或智能指针传递的优缺点.然后决定.
我在这里看到的破碎设计的唯一标志是你朋友的盲目宗教.
也就是说,有一些签名没有带来太大的影响.按值取一个const可能很愚蠢,因为如果你保证不改变对象那么你也可以不自己制作它.当然,除非它是一个原语,在这种情况下,编译器可以足够聪明,仍然可以参考.或者,有时将指针指针作为参数是笨拙的.这增加了复杂性; 相反,您可以通过引用指针来逃避它,并获得相同的效果.
但是不要把这些指导原则放在一边; 总是考虑你的选择,因为没有正式的证据可以消除任何替代方案的用处.
原因是他觉得"通过引用传递物体是一种破碎设计的标志".
虽然纯粹出于技术原因这在C++中是错误的,但总是使用pass-by-value对于初学者来说是一个足够好的近似 - 它肯定比通过指针传递所有内容要好得多(或者甚至比通过引用传递所有内容更好).它会使一些代码效率低下,但是,嘿!只要这不打扰你的朋友,不要被这种做法不适当地打扰.只是提醒他,总有一天他可能想重新考虑一下.
另一方面,这个:
有一些大的控制器对象,但没有比这复杂.
是个问题.您的朋友在谈论破裂的设计,然后把所有的代码使用几个3D矢量和大型控制结构?那是一个破碎的设计.好的代码通过使用数据结构实现了模块化.似乎并非如此.
...一旦你使用这样的数据结构,没有按引用传递的代码可能确实变得非常低效.
我认为问题本身存在巨大的误解.
一方面堆栈或堆分配的对象之间没有关系,另一方面传递值或引用或指针.
堆栈与堆分配
在可能的情况下总是更喜欢堆栈,然后为您管理对象的生命周期,这更容易处理.
但在某些情况下可能无法实现:
我可能会错过一些,但在这种情况下,您应该使用SBRM(Scope Bound Resources Management)来利用堆栈生存期管理功能,例如使用智能指针.
通过:值,引用,指针
首先,语义有所不同:
请注意,默认情况下,某些语言(像Haskell这样的功能类型)不提供引用/指针.一旦创建,值就是不可变的.除了处理外部环境的一些解决方法之外,它们不受此使用的限制,并且它以某种方式使调试更容易.
你的朋友应该知道传递引用或传递指针绝对没有问题:例如swap,它不能用pass-by-value实现.
最后,多态性不允许按值传递语义.
现在,让我们谈谈表演.
它通常是得到普遍认同的内置插件应该按值传递(以避免间接)和用户定义的大课,应参照/指针传递(避免复制).大实际上通常意味着拷贝构造函数是不平凡的.
然而,有一个关于小型用户定义类的开放性问题.最近发表的一些文章表明,在某些情况下,按值传递可能允许从编译器进行更好的优化,例如,在这种情况下:
Object foo(Object d) { d.bar(); return d; }
int main(int argc, char* argv[])
{
Object o;
o = foo(o);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这里,智能编译器能够确定o可以在没有任何复制的情况下进行修改!(我认为函数定义必须是可见的,我不知道Link-Time Optimization是否能解决这个问题)
因此,性能问题只有一种可能性,例如:测量.
| 归档时间: |
|
| 查看次数: |
1623 次 |
| 最近记录: |