![]() |
1
14
子类型多态性是这样一种情况:传递值不起作用,因为您将派生类切片为其基类。也许对某些人来说,使用子类型多态性是不好的设计? |
![]() |
2
6
在没有使用引用的情况下,有各种各样的事情是无法完成的——从一个复制构造函数开始。引用(或指针)是基本的,不管他喜欢与否,他都在使用引用。(引用的一个优点,或者可能是缺点是,一般来说,您不必更改代码来传递(const)引用。)而且大多数时候没有理由不使用引用。 是的,对于没有动态分配要求的小对象来说,传递值是可以的,但是通过说“没有引用”而不进行具体的测量,使自己陷入困境仍然是愚蠢的,所谓的开销(a)是可感知的,(b)是显著的。过早的优化是万恶之源” 一 . 一 各种属性,包括 C A Hoare (尽管他显然否认了这一点)。 |
![]() |
3
6
你朋友的问题不在于他的想法,而在于他的宗教信仰。对于任何函数,总是考虑按值、引用、常量引用、指针或智能指针传递的优缺点。然后决定。 我在这里看到的唯一破碎设计的迹象就是你朋友的盲目信仰。 也就是说,有一些签名并没有带来什么好处。按值取常量可能是愚蠢的,因为如果你保证不改变对象,那么你最好不要自己复制它。当然,除非它是一个原语,在这种情况下,编译器可以足够聪明地获取引用。或者,有时把指向指针的指针作为参数是很笨拙的。这增加了复杂性;相反,通过引用一个指针,您可能能够摆脱它,并获得相同的效果。 但不要把这些指导方针视为一成不变的;要始终考虑你的选择,因为没有正式的证据可以消除任何选择的有用性。
|
![]() |
4
5
尽管C++在纯技术方面是错误的,但是总是使用传递值对初学者来说是一个很好的近似。 许多的 比通过指针传递所有东西(或者甚至比通过引用传递所有东西)更好。这会使一些代码效率低下,但是,嘿!只要这不打扰你的朋友,不要被这种做法过度打扰。提醒他,总有一天他可能会想重新考虑。 另一方面,这:
是 一个问题。你的朋友说的是坏的设计,然后所有的代码使用的是一些三维向量和大型控制结构? 那 是一个破碎的设计。好的代码通过使用数据结构实现模块化。似乎情况并非如此。 _浼浼浼浼浼浼浼浼浼浼浼 |
![]() |
5
5
我认为这个问题本身存在一个巨大的误解。 一方面,堆栈或堆分配对象与另一方面的传递值、引用或指针之间没有关系。 堆栈与堆分配 如果可能的话,总是更喜欢堆栈,对象的生命周期随后会为您管理,这更容易处理。 但是,在以下几种情况下可能无法实现:
我可能会错过一些,但在本例中,您应该使用SBRM(范围绑定资源管理)来利用堆栈的生存期管理功能,例如使用智能指针。 传递:值、引用、指针 首先,不同的是 语义 :
请注意,默认情况下,某些语言(像haskell这样的函数类型)不提供引用/指针。一旦创建,这些值就不可变。除了一些处理外部环境的工作区之外,它们并没有受到这种使用的限制,而且它以某种方式使调试更容易。
你的朋友应该知道传递引用或传递指针绝对没有任何错误:例如
最后,多态性不允许传递值语义。 现在,让我们谈谈表演。 通常很好地接受内建应该按值传递(以避免间接传递)和用户定义 大的 类应该通过引用/指针传递(以避免复制)。 大的 实际上,通常意味着复制构造函数并不简单。 然而,关于 小的 用户定义的类。最近发表的一些文章建议,在某些情况下,传递值可能允许从编译器进行更好的优化,例如,在这种情况下:
在这里,智能编译器可以确定
因此,性能问题只有一种可能,就像往常一样: 测量 . |
![]() |
6
3
首先,除了递归情况外,堆栈很少溢出此网站。 关于他的推理,我认为他可能是错的,因为他太笼统了,但是 他所做的 可能是正确的…或不是?
例如,Windows窗体库使用
但是,由于我看不到代码,我觉得我不应该评判他做了什么,尽管我觉得他可能做了正确的事情,尽管他的想法过于笼统。 |
![]() |
7
3
这并不像你想象的那么明显。C++编译器非常积极地执行复制删除操作,因此您通常可以通过值而不会导致复制操作的成本。在某些情况下,通过价值传递 might even be faster . 在出于性能原因谴责这个问题之前,您至少应该生成支持它的基准。它们可能很难被创造出来 因为 编译器通常消除性能差异。 所以真正的问题应该是语义学。您希望代码的行为如何?有时,引用语义是您想要的,然后您应该通过引用传递。如果您特别想要/需要值语义,那么就通过值传递。 有一点有利于传递值。它有助于实现更具功能性的代码风格,副作用更少,并且在默认情况下不可变。这使得许多代码更容易解释,而且也可能使代码并行化更容易。 但事实上,两者都有自己的位置。和 从未 使用旁路参考绝对是一个大的警告标志。 在过去6个月左右的时间里,我一直在尝试将旁路值作为默认值。如果我不显式地需要引用语义,那么我尝试假定编译器将为我执行复制省略,这样我就可以通过值传递而不损失任何效率。 到目前为止,编译器还没有让我失望。我肯定我会遇到一些情况,我必须回去把一些电话改为通过引用,但我知道后会这样做的
|
![]() |
8
3
我会这么说的 在C语言中不使用指针是新手程序员的标志。 听起来你的朋友害怕指点。 记住,C++指针实际上是从C语言继承的,而C是在计算机不那么强大的时候开发出来的。然而,直到今天,速度和效率仍然至关重要。 那么,为什么要使用指针呢? 它们允许开发人员优化一个程序,使其运行速度更快,或者使用更少的内存,否则的话!引用数据的内存位置比复制周围的所有数据更有效。 指针通常是一个概念,对于那些开始编程的人来说很难理解,因为所有的实验都涉及到小的数组,也许是一些结构,但基本上,当你有1GB的内存在家里的时候,它们包括使用几兆字节(如果你幸运的话)。在这个场景中,几个MB什么都不是,通常对程序的性能影响很小。 让我们稍微夸大一下。想到一个 字符数组 对于2147483648个元素(2GB的数据),您需要传递给函数,函数将所有数据写入磁盘。现在,你认为什么技术更有效/更快?
当你没有4GB内存时会发生什么?你会不会仅仅因为害怕使用指针而花美元购买RAM芯片? 在不必复制的情况下,重新复制内存中的数据听起来有点多余,这浪费了计算机资源。 不管怎样,对你的朋友要有耐心。如果他想在一生中的某个时刻成为一个严肃的/专业的程序员,他最终将不得不花时间真正理解指针。 祝你好运。 |
![]() |
9
2
正如前面提到的,引用和指针之间的最大区别在于指针可以为空。如果类需要数据,引用声明将使其成为必需的。如果调用方希望这样做,则添加const将使其“只读”。 提到的传递值“缺陷”只是不正确。按值传递所有内容将完全改变应用程序的性能。当基元类型(如int、double等)通过值传递时,情况也不错,但当类实例通过值传递时,会创建临时对象,这要求对类和类中的所有成员变量调用构造函数和析构函数。当使用大型类层次结构时,这会很恼火,因为必须同时调用父类构造函数/析构函数。 而且,仅仅因为向量是通过值传递的,并不意味着它只使用堆栈内存。堆可以用于每个元素,因为它是在传递给方法/函数的临时向量中创建的。如果向量达到其容量,它本身也可能需要通过堆重新分配。 如果传递值的作用是不修改调用方的值,那么只需使用常量引用。 |
![]() |
10
2
到目前为止,我看到的答案都集中在性能上:引用传递比值传递更快的情况。如果你专注于那些不可能通过价值传递的案例,你的论点可能会更成功。 小元组或向量是一种非常简单的数据结构类型。更复杂的数据结构共享信息,而共享不能直接表示为值。您要么需要使用引用/指针,要么使用模拟它们的东西,如数组和索引。 许多问题归结为形成一个图或有向图的数据。在这两种情况下,都有需要存储在数据结构中的边和节点的混合。现在您有一个问题,相同的数据需要在多个地方。如果避免引用,那么首先需要复制数据,然后在其他副本中仔细复制每个更改。 你朋友的论点归结为:解决任何复杂到可以用图表表示的问题都是一个糟糕的设计…… |
![]() |
11
2
哦,天哪,从哪里开始……
我可以继续说下去。 如果你的朋友对图形感兴趣,他应该看看图形中常用的一些API:Linux上的OpenGL和XWindows,Mac OS X上的Quartz,Windows上的Direct X。他应该看看大型C/C++系统的内部结构,比如WebKIT或GECKO HTML渲染引擎,或者任何Mozilla浏览器,或者GTK+或QT-GUI工具包。它们都通过任何比单个整数或引用浮点大得多的值传递,并且通常通过引用而不是作为函数返回值来填充结果。 没有任何严重的现实世界C/C++CHOPS -我的意思是 没有人 -按值传递数据结构。这是有原因的:它只是翻转效率低下和容易出现问题。 |
![]() |
12
1
哇,已经有13个答案了我没有详细阅读,但我认为这和其他答案有很大的不同。 他说得有道理。按规则传递值的优点是子例程不能细微地修改其参数。经过 非常量 参考文献表明,每个函数都有难看的副作用,表明设计不好。
简单地向他解释
|
![]() |
13
0
给你的朋友买一本好的C++书籍。通过引用传递非平凡的对象是一个很好的实践,可以节省大量不必要的构造函数/析构函数调用。这也与在自由存储上分配和使用堆栈无关。您可以(或者应该)通过引用传递程序堆栈上分配的对象,而不需要使用任何自由存储。你也可以完全忽略免费商店,但这会让你回到你的朋友可能没有想到的旧Fortran时代-否则他会为你的项目选择一个古老的F77编译器,不是吗…? |
![]() |
Tono Nam · 无法在golang中通过引用修改对象 2 年前 |
![]() |
uzivanky · 课堂上不同的“this” 6 年前 |
![]() |
Henry Marshall · 通过引用替换JS对象[重构工作代码] 7 年前 |
|
user9441223 · 通过引用传递对象并将其存储为成员变量 7 年前 |
![]() |
Enryu · 参考变量参数vs局部参考变量[关闭] 7 年前 |
![]() |
Tryer · 计算不同类别对象的数量 7 年前 |