在 C++ 中仅使用堆栈的后果
假设我认识一个 C++ 新手。他不传递指针(这是正确的),但他拒绝通过引用传递。他总是使用按值传递。原因是他认为“通过引用传递对象是设计失败的标志”。
该程序是一个小型图形程序,大多数传递的问题是数学向量(3元组)对象。有一些大的控制器对象,但没有比这更复杂的了。
我发现很难找到反对只使用堆栈的有力论据。
我认为按值传递对于向量等小对象来说是很好的,但即使这样,代码中也会发生很多不必要的复制。按值传递大型对象显然是浪费,而且很可能不是您想要的功能。
从优点来看,我相信堆栈在分配/释放内存方面更快,并且具有恒定的分配时间。
我能想到的唯一主要论点是堆栈可能会溢出,但我猜测这种情况不太可能发生?是否还有其他反对仅使用堆栈/按值传递而不是按引用传递的论点?
Lets say I know a guy who is new to C++. He does not pass around pointers (rightly so) but he refuses to pass by reference. He uses pass by value always. Reason being that he feels that "passing objects by reference is a sign of a broken design".
The program is a small graphics program and most of the passing in question is mathematical Vector(3-tuple) objects. There are some big controller objects but nothing more complicated than that.
I'm finding it hard to find a killer argument against only using the stack.
I would argue that pass by value is fine for small objects such as vectors but even then there is a lot of unnecessary copying occurring in the code. Passing large objects by value is obviously wasteful and most likely not what you want functionally.
On the pro side, I believe the stack is faster at allocating/deallocating memory and has a constant allocation time.
The only major argument I can think of is that the stack could possibly overflow, but I'm guessing that it is improbable that this will occur? Are there any other arguments against using only the stack/pass by value as opposed to pass by reference?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
子类型多态性是按值传递不起作用的情况,因为您会将派生类切片为其基类。也许对某些人来说,使用子类型多态性是糟糕的设计?
Subtyping-polymorphism is a case where passing by value wouldn't work because you would slice the derived class to its base class. Maybe to some, using subtyping-polymorphism is bad design?
你朋友的问题不在于他的想法,而在于他的宗教信仰。对于任何函数,请始终考虑按值、引用、常量引用、指针或智能指针传递的优缺点。然后决定。
我在这里看到的唯一破损设计的迹象是你朋友的盲目宗教。
也就是说,有一些签名并没有带来太多好处。按值获取 const 可能很愚蠢,因为如果您承诺不更改该对象,那么您可能也不会创建自己的副本。当然,除非它是原语,在这种情况下,编译器可以足够聪明,仍然可以获取引用。或者,有时将指向指针的指针作为参数是很笨拙的。这增加了复杂性;相反,您可以通过引用指针来摆脱它,并获得相同的效果。
但不要将这些指导方针视为一成不变的。始终考虑您的选择,因为没有正式的证据可以消除任何替代方案的有用性。
Your friend's problem is not his idea as much as his religion. Given any function, always consider the pros and cons of passing by value, reference, const reference, pointer or smart pointer. Then decide.
The only sign of broken design I see here is your friend's blind religion.
That said, there are a few signatures that don't bring much to the table. Taking a const by value might be silly, because if you promise not to change the object then you might as well not make your own copy of it. Unless its a primitive, of course, in which case the compiler can be smart enough to take a reference still. Or, sometimes it's clumsy to take a pointer to a pointer as argument. This adds complexity; instead, you might be able to get away with it by taking a reference to a pointer, and get the same effect.
But don't take these guidelines as set in stone; always consider your options because there is no formal proof that eliminates any alternative's usefulness.
有各种各样的事情如果不使用引用就无法完成 - 从复制构造函数开始。引用(或指针)是基础,无论他是否喜欢,他都在使用引用。 (引用的一个优点(也可能是缺点)是,一般来说,您不必更改代码来传递(const)引用。)并且没有理由在大多数情况下不使用引用。
是的,对于不需要动态分配的小对象来说,按值传递是可以的,但是在没有具体测量所谓的开销是(a)可感知和(b)显着的情况下说“无引用”来束缚自己仍然是愚蠢的。 “过早的优化是万恶之源”1。
1
各种归因,包括CA Hoare(尽管他显然否认这一点)。
There are all sorts of things that cannot be done without using references - starting with a copy constructor. References (or pointers) are fundamental and whether he likes it or not, he is using references. (One advantage, or maybe disadvantage, of references is that you do not have to alter the code, in general, to pass a (const) reference.) And there is no reason not to use references most of the time.
And yes, passing by value is OK for smallish objects without requirements for dynamic allocation, but it is still silly to hobble oneself by saying "no references" without concrete measurements that the so-called overhead is (a) perceptible and (b) significant. "Premature optimization is the root of all evil"1.
1
Various attributions, including C A Hoare (although apparently he disclaims it).
我认为这个问题本身就存在很大的误解。
一方面,堆栈或堆分配的对象之间没有关系,另一方面,通过值、引用或指针传递。
堆栈与堆分配
如果可能的话,总是更喜欢堆栈,然后为您管理对象的生命周期,这更容易处理。
但在某些情况下这可能是不可能的:
我可能会错过一些,但在这种情况下你应该使用 SBRM(范围限制资源)管理)以利用堆栈生命周期管理功能,例如通过使用智能指针。
传递方式:值、引用、指针
首先,有一个语义的区别:
请注意,某些语言(如 Haskell 的函数类型)默认不提供引用/指针。这些值一旦创建就不可更改。除了一些处理外部环境的解决方法之外,它们不受这种用途的限制,并且在某种程度上使调试变得更容易。
你的朋友应该知道,按引用传递或按指针传递绝对没有问题:例如
交换
,它不能用按值传递来实现。最后,多态性不允许传递值语义。
现在,我们来谈谈表演。
人们通常认为内置函数应按值传递(以避免间接),而用户定义的大类应按引用/指针传递(以避免复制)。 大实际上通常意味着复制构造函数并不简单。
然而,关于小型用户定义的类还有一个悬而未决的问题。最近发表的一些文章表明,在某些情况下,按值传递可能允许编译器进行更好的优化,例如,在这种情况下:
这里,智能编译器能够确定
o
可以在没有任何复制的地方! (我认为函数定义必须可见,我不知道链接时优化是否会解决这个问题)因此,性能问题只有一种可能性,就像往常一样:测量。
I think there is a huge misunderstanding in the question itself.
There is not relationship between stack or heap allocated objects on the one hand and pass by value or reference or pointer on the other.
Stack vs Heap allocation
Always prefer stack when possible, the object's lifetime is then managed for you which is much easier to deal with.
It might not be possible in a couple of situations though:
And I might miss some, but in this case you should use SBRM (Scope Bound Resources Management) to leverage the stack lifetime management abilities, for example by using smart pointers.
Pass by: value, reference, pointer
First of all, there is a difference of semantics:
Note that some languages (the functional kind like Haskell) do not offer reference/pointer by default. The values are immutable once created. Apart from some work-arounds for dealing with the exterior environment, they are not that restricted by this use and it somehow makes debugging easier.
Your friend should learn that there is absolutely nothing wrong with pass-by-reference or pass-by-pointer: for example thing of
swap
, it cannot be implemented with pass-by-value.Finally, Polymorphism does not allow pass-by-value semantics.
Now, let's speak about performances.
It's usually well accepted that built-ins should be passed by value (to avoid an indirection) and user-defined big classes should be passed by reference/pointer (to avoid copying). big in fact generally means that the Copy Constructor is not trivial.
There is however an open question regarding small user-defined classes. Some articles published recently suggest that in some case pass-by-value might allow better optimization from the compiler, for example, in this case:
Here a smart compiler is able to determine that
o
can be modified in place without any copying! (It is necessary that the function definition be visible I think, I don't know if Link-Time Optimization would figure it out)Therefore, there is only one possibility to the performance issue, like always: measure.
尽管出于纯粹的技术原因,这在 C++ 中是错误的,但对于初学者来说,始终使用按值传递是一个足够好的近似值 - 它肯定比通过指针传递所有内容(或者甚至比通过指针传递所有内容)要好得多。参考)。它会使一些代码效率低下,但是,嘿!只要这不打扰你的朋友,就不要因这种做法而过度打扰。只是提醒他,有一天他可能会重新考虑。
另一方面,这个:
是一个问题。你的朋友正在谈论破碎的设计,然后所有代码使用的都是一些 3D 向量和大型控制结构? 那是一个糟糕的设计。好的代码通过使用数据结构来实现模块化。事实似乎并非如此。
…一旦你使用这样的数据结构,没有引用传递的代码确实可能变得非常低效。
Although this is wrong in C++ for purely technical reasons, always using pass-by-value is a good enough approximation for beginners – it’s certainly much better than passing everything by pointers (or perhaps even than passing everything by reference). It will make some code inefficient but, hey! As long as this doesn’t bother your friend, don’t be unduly disturbed by this practice. Just remind him that someday he might want to reconsider.
On the other hand, this:
is a problem. Your friend is talking about broken design, and then all the code uses are a few 3D vectors and large control structures? That is a broken design. Good code achieves modularity through the use of data structures. It doesn’t seem as though this were the case.
… And once you use such data structures, code without pass-by-reference may indeed become quite inefficient.
首先,除了递归情况外,堆栈很少在该网站之外溢出。
关于他的推理,我认为他可能是错误的,因为他太笼统了,但他所做的可能是正确的......或者不是?
例如,Windows Forms 库使用有 4 个成员的 Rectangle 结构,Apple 的 QuartzCore 也有 CGRect 结构,并且这些结构总是按值传递。 >。我认为我们可以将其与具有 3 个浮点变量的 Vector 进行比较。
然而,由于我没有看到代码,我觉得我不应该判断他做了什么,尽管我有一种感觉,尽管他的想法过于笼统,但他可能做了正确的事情。
First thing is, stack rarely overflows outside this website, except in the recursion case.
About his reasoning, I think he might be wrong because he is too generalized, but what he has done might be correct... or not?
For example, the Windows Forms library use
Rectangle
struct that have 4 members, the Apple's QuartzCore also hasCGRect
struct, and those structs always passed by value. I think we can compare that to Vector with 3 floating-point variable.However, as I do not see the code, I feel I should not judge what he has done, though I have a feeling he might did the right thing despite of his over generalized idea.
它并不像您想象的那么明显。 C++ 编译器非常积极地执行复制省略,因此您通常可以按值传递,而不会产生复制操作的成本。在某些情况下,按值传递 甚至可能是更快。
在出于性能原因谴责该问题之前,您至少应该生成基准来支持它。而且它们可能很难创建,因为编译器通常会消除性能差异。
所以真正的问题应该是语义之一。您希望您的代码表现如何?有时,引用语义就是您想要的,那么您应该通过引用传递。如果您特别想要/需要值语义,那么您可以按值传递。
有一点赞成按值传递。它有助于实现更实用的代码风格,副作用更少,并且默认不变性。这使得很多代码更容易推理,并且也可能使代码的并行化变得更容易。
但事实上,两者都有自己的位置。 从不使用引用传递绝对是一个很大的警告信号。
在过去 6 个月左右的时间里,我一直在尝试将值传递设置为默认值。如果我没有明确需要引用语义,那么我会尝试假设编译器将为我执行复制省略,这样我就可以按值传递而不会损失任何效率。
到目前为止,编译器并没有真正让我失望。我确信我会遇到必须返回并更改一些调用以通过引用传递的情况,但是当我知道
It's not quite as obvious as you might think. C++ compilers perform copy elision very aggressively, so you can often pass by value without incurring the cost of a copy operation. And in some cases, passing by value might even be faster.
Before condemning the issue for performance reasons, you should at the very least produce the benchmarks to back it up. And they might be hard to create because the compiler typically eliminates the performance difference.
So the real issue should be one of semantics. How do you want your code to behave? Sometimes, reference semantics are what you want, and then you should pass by reference. If you specifically want/need value semantics then you pass by value.
There is one point in favor of passing by value. It's helpful in achieving a more functional style of code, with fewer side effects and where immutability is the default. That makes a lot of code easier to reason about, and it may make it easier to parallelize the code as well.
But in truth, both have their place. And never using pass-by-reference is definitely a big warning sign.
For the last 6 months or so, I've been experimenting with making pass-by-value the default. If I don't explicitly need reference semantics, then I try to assume that the compiler will perform copy elision for me, so I can pass by value without losing any efficiency.
So far, the compiler hasn't really let me down. I'm sure I'll run into cases where I have to go back and change some calls to passing by reference, but I'll do that when I know that
我想说,在 C 中不使用指针是新手程序员的标志。
听起来你的朋友害怕指针。
请记住,C++ 指针实际上是从 C 语言继承的,而 C 是在计算机还没有那么强大的时候开发的。尽管如此,直到今天,速度和效率仍然至关重要。
那么,为什么要使用指针?它们允许开发人员优化程序,使其运行得更快或使用更少的内存!引用数据的内存位置比复制周围的所有数据要有效得多。
对于那些刚开始编程的人来说,指针通常是一个很难掌握的概念,因为所做的所有实验都涉及小型数组,可能还有一些结构,但基本上它们包括在您使用时使用几兆字节(如果您幸运的话)。家里有 1GB 的内存。在这个场景中,几 MB 不算什么,而且通常太小,无法对程序的性能产生重大影响。
所以让我们夸大一点。想象一个包含 2147483648 个元素(2GB 数据)的 char 数组,您需要将其传递给将所有数据写入磁盘的函数。现在,您认为哪种技术会更有效/更快?
如果您没有 4GB RAM,会发生什么情况?你会因为害怕使用指针而花美元购买 RAM 芯片吗?
当您不需要时,重新复制内存中的数据听起来有点多余,而且浪费计算机资源。
不管怎样,对你的朋友要有耐心。如果他想在生命中的某个时刻成为一名严肃/专业的程序员,他最终将不得不花时间真正理解指针。
祝你好运。
I would say that Not using pointers in C is a sign of a newbie programmer.
It sounds like your friend is scared of pointers.
Remember, C++ pointers were actually inherited from the C language, and C was developed when computers were much less powerful. Nevertheless, speed and efficiency continue to be vital until this day.
So, why use pointers? They allow the developer to optimize a program to run faster or use less memory that it would otherwise! Referring to the memory location of a data is much more efficient then copying all the data around.
Pointers usually are a concept that is difficult to grasp for those beginning to program, because all the experiments done involve small arrays, maybe a few structs, but basically they consist of working with a couple of megabytes (if you're lucky) when you have 1GB of memory laying around the house. In this scene, a couple of MB are nothing and it usually is too little to have a significant impact on the performance of your program.
So let's exaggerate that a little bit. Think of a char array with 2147483648 elements - 2GB of data - that you need to pass to function that will write all the data to the disk. Now, what technique do you think is going to be more efficient/faster?
What happens when you just don't have 4GB of RAM? Will you spend $ and buy chips of RAM just because you are afraid of using pointers?
Re-copying the data in memory sounds a bit redundant when you don't have to, and its a waste of computer resource.
Anyway, be patient with your friend. If he would like to become a serious/professional programmer at some point in his life he will eventually have to take the time to really understand pointers.
Good Luck.
正如已经提到的,引用和指针之间的最大区别是指针可以为空。如果一个类需要数据,则引用声明将使其成为必需的。如果调用者需要的话,添加 const 将使其“只读”。
提到的按值传递“缺陷”根本不是真的。按值传递所有内容将彻底改变应用程序的性能。当基本类型(即 int、double 等)按值传递时,情况还不错,但当类实例按值传递时,会创建临时对象,这需要在类和所有对象上调用构造函数和析构函数。类中的成员变量。当使用大型类层次结构时,这会变得很恼火,因为还必须调用父类构造函数/析构函数。
此外,仅仅因为向量按值传递并不意味着它只使用堆栈内存。堆可用于每个元素,因为它是在传递给方法/函数的临时向量中创建的。如果向量本身达到其容量,也可能必须通过堆重新分配。
如果按值传递以便调用者值不会被修改,则只需使用 const 引用。
As already mentioned the big difference between a reference and a pointer is that a pointer can be null. If a class requires data a reference declaration will make it required. Adding const will make it 'read only' if that is what is desired by the caller.
The pass-by-value 'flaw' mentioned is simply not true. Passing everything by value will completely change the performance of an application. It is not so bad when primitive types (i.e. int, double, etc.) are passed by value but when a class instance is passed by value temporary objects are created which requires constructors and later on destructor's to be called on the class and on all of the member variable in the class. This is exasperated when large class hierarchies are used because parent class constructors/destructor's must be called as well.
Also, just because the vector is passed by value does not mean that it only uses stack memory. heap may be used for each element as it is created in the temporary vector that is passed to the method/function. The vector itself may also have to reallocate via heap if it reaches its capacity.
If pass by value is being so that the callers values are not modified then just use a const reference.
到目前为止我看到的答案都集中在性能上:按引用传递比按值传递更快的情况。如果您关注通过值传递不可能实现的情况,您的论证可能会更成功。
小元组或向量是一种非常简单的数据结构类型。更复杂的数据结构共享信息,并且这种共享不能直接表示为值。您需要使用引用/指针或模拟它们的东西,例如数组和索引。
许多问题都归结为形成图或有向图的数据。在这两种情况下,您都有需要存储在数据结构中的边和节点的混合。现在您遇到的问题是相同的数据需要位于多个位置。如果避免引用,那么首先需要复制数据,然后需要在其他每个副本中仔细复制每个更改。
你朋友的论点归结为:解决任何复杂到足以用图来表示的问题都是一个糟糕的设计......
The answers that I've seen so far have all focused on performance: cases where pass-by-reference is faster than pass-by-value. You may have more success in your argument if you focus on cases that are impossible with pass-by-value.
Small tuples or vectors are a very simple type of data-structure. More complex data-structures share information, and that sharing can't be represented directly as values. You either need to use references/pointers or something that simulates them such as arrays and indices.
Lots of problems boil down to data that forms a Graph, or a Directed-Graph. In both cases you have a mixture of edges and nodes that need to be stored within the data-structure. Now you have the problem that the same data needs to be in multiple places. If you avoid references then firstly the data needs to be duplicated, and then every change needs to be carefully replicated in each of the other copies.
Your friend's argument boils down to saying: tackling any problem complex enough to be represented by a Graph is a bad-design....
好吧,天哪,从哪里开始......
正如您提到的,“代码中发生了很多不必要的复制”。假设您有一个循环,可以在这些对象上调用函数。使用指针而不是复制对象可以将执行速度加快一个或多个数量级。
您不能在堆栈上传递可变大小的数据结构、数组等。您必须动态分配它并传递指向开头的指针或引用。如果您的朋友没有遇到过这种情况,那么是的,他是“C++ 新手”。
正如您所提到的,所讨论的程序很简单,并且主要使用非常小的对象,例如图形 3 元组,如果元素是双精度数,则每个对象将是 24 字节。但在图形中,通常处理 4x4 数组,它可以处理旋转和平移。这些将是每个 128 字节,因此,如果一个程序必须处理这些,由于增加的复制,每次使用值传递的函数调用都会慢五倍。通过引用传递,在 32 位可执行文件中传递 3 元组或 4x4 数组只需要复制单个 4 字节指针。
在寄存器丰富的 CPU 架构上,例如 ARM、PowerPC、64 位 x86、680x0(但不是 32 位 x86),指针(和引用,它们是穿着奇特语法服装的秘密指针)通常以与堆栈操作中涉及的内存访问相比,这确实快得惊人。
您提到不太可能耗尽堆栈空间。是的,这就是人们可能为课堂作业编写的一个小程序。但几个月前,我正在调试商业代码,其中 main() 下面可能有 80 个函数调用。如果他们使用按值传递而不是按引用传递,则堆栈将变得巨大。以免你的朋友认为这是一个“糟糕的设计”,这实际上是一个使用 GTK+ 在 Linux 上实现的基于 WebKit 的浏览器,所有这些都是非常先进的,并且函数调用深度对于专业代码来说是正常的.
一些可执行架构限制单个堆栈帧的大小,因此即使您本身可能没有用完堆栈空间,您也可能会超出这个范围并最终得到无法在此类平台上构建的完全有效的 C++ 代码 一些可执行架构限制单个堆栈帧的大小,因此
我还可以继续说下去。
如果你的朋友对图形感兴趣,他应该看一下图形中使用的一些常见 API:Linux 上的 OpenGL 和 XWindows、Mac OS X 上的 Quartz、Windows 上的 Direct X。他应该研究大型 C/C++ 系统的内部结构,例如 WebKit 或 Gecko HTML 渲染引擎,或任何 Mozilla 浏览器,或 GTK+ 或 Qt GUI 工具包。它们都通过引用传递比单个整数或浮点大得多的任何内容,并且通常通过引用而不是作为函数返回值填充结果。
现实世界中没有人具有任何真正的 C/C++ 能力 - 我的意思是没有人 - 按值传递数据结构。这是有原因的:它只是效率低下且容易出现问题。
Well, gosh, where to start...
As you mention, "there is a lot of unnecessary copying occurring in the code". Let's say you've got a loop where you call a function on these objects. Using a pointer instead of duplicating the objects can accelerate execution by one or more orders of magnitude.
You can't pass a variable-sized data structures, arrays, etc. around on the stack. You have to dynamically allocate it and pass a pointers or reference to the beginning. If your friend hasn't run into this, then yes, he's "new to C++."
As you mention, the program in question is simple and mostly uses quite small objects like graphics 3-tuples, which if the elements are doubles would be 24 bytes apiece. But in graphics, it's common to deal with 4x4 arrays, which handle both rotation and translation. Those would be 128 bytes apiece, so if a program that had to deal with those would be five times slower per function call with pass-by-value due to the increased copying. With pass-by-reference, passing a 3-tuple or a 4x4 array in a 32-bit executable would just involve duplicating a single 4-byte pointer.
On register-rich CPU architecures like ARM, PowerPC, 64-bit x86, 680x0 - but not 32-bit x86 - pointers (and references, which are secretly pointers wearing fancy syntatical clothing) are commonly be passed or returned in a register, which is really freaking fast compared to the memory access involved in a stack operation.
You mention the improbability of running out of stack space. And yes, that's so on a small program one might write for a class assignment. But a couple of months ago, I was debugging commercial code that was probably 80 function calls below main(). If they'd used pass-by-value instead of pass-by-reference, the stack would have been ginormous. And lest your friend think this was a "broken design", this was actually a WebKit-based browser implemented on Linux using GTK+, all of which is very state-of-the-art, and the function call depth is normal for professional code.
Some executable architectures limit the size of an individual stack frame, so even though you might not run out of stack space per se, you could exceed that and wind up with perfectly valid C++ code that wouldn't build on such a platform.
I could go on and on.
If your friend is interested in graphics, he should take a look at some of the common APIs used in graphics: OpenGL and XWindows on Linux, Quartz on Mac OS X, Direct X on Windows. And he should look at the internals of large C/C++ systems like the WebKit or Gecko HTML rendering engines, or any of the Mozilla browsers, or the GTK+ or Qt GUI toolkits. They all pass by anything much larger than a single integer or float by reference, and often fill in results by reference rather than as a function return value.
Nobody with any serious real world C/C++ chops - and I mean nobody - passes data structures by value. There's a reason for this: it's just flipping inefficient and problem-prone.
哇,已经有 13 个答案了……我没有详细阅读所有内容,但我认为这与其他答案有很大不同……
他说得有道理。通常,按值传递的优点是子例程无法巧妙地修改其参数。传递非常量引用将表明每个函数都有丑陋的副作用,表明设计不佳。
只需向他解释
vector3 &
和vector3 const&
之间的区别,并演示后者如何通过常量初始化,如vec_function( vector3(1 ,2,3) );
,但不是前者。通过常量引用传递是对值传递的简单优化。Wow, there are already 13 answers… I didn't read all in detail but I think this is quite different from the others…
He has a point. The advantage of pass-by-value as a rule is that subroutines cannot subtly modify their arguments. Passing non-const references would indicate that every function has ugly side effects, indicating poor design.
Simply explain to him the difference between
vector3 &
andvector3 const&
, and demonstrate how the latter may be initialized by a constant as invec_function( vector3(1,2,3) );
, but not the former. Pass by const reference is a simple optimization of pass by value.给你的朋友买一本好的 C++ 书。通过引用传递重要对象是一种很好的做法,可以节省大量不必要的构造函数/析构函数调用。这也与在自由存储上分配与使用堆栈无关。您可以(或应该)通过引用传递在程序堆栈上分配的对象,而无需使用任何空闲存储。您也可以完全忽略免费存储,但这会让您回到旧的 Fortran 时代,而您的朋友可能没有想到这一点 - 否则他会为您的项目选择一个古老的 f77 编译器,不是......?
Buy your friend a good c++ book. Passing non-trivial objects by reference is a good practice and saves you a lot of unneccessary constructor/destructor calls. This has also nothing to do with allocating on free store vs. using stack. You can (or should) pass objects allocated on program stack by reference without any free store usage. You also can ignore free store completely, but that throws you back to the old fortran days which your friend probably hadn't in mind - otherwise he would pick an ancient f77 compiler for your project, wouldn't he...?