一般问题:在 C/C++ 中作为指针传递什么?
嘿, 我想知道是否值得通过指针传递原始单值,例如 int、float、double 或 char?可能不值得吧!?但是,如果您只是通过指针传递所有内容,这是否会使程序变慢? 你应该总是只将数组作为指针传递吗? 谢谢!
Hey there,
I wonder if it's worth passing primitive single values like int
, float
, double
or char
by pointer? Probably it's not worth!? But if you would simply pass everything by pointer, is this making the program slower?
Should you always just pass arrays as pointer?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
你想实现什么目标?您希望能够写入传入的值吗?或者您只需要使用它?如果你想写入它,惯用的方法是通过引用传递。如果您不需要写入它,则最好避免意外写入并按值传递的任何风险。按值传递将制作变量的副本以供本地使用。 (顺便说一句,如果您不想复制并想要一定程度的安全性,您可以通过 const 引用)
很难说。取决于很多事情。在按值传递和按引用(或指针)传递中,您都创建了新的原始类型。在按值传递中,您正在制作副本。在通过引用/指针传递时,您将一个地址传递给原始地址。然而,在后一种情况下,您需要额外获取可能会或可能不会被缓存的内存。如果不进行测量,很难说 100%。
话虽如此,我怀疑差异是否明显。编译器可能能够在许多按值传递的情况下优化副本,如 文章。 (感谢空间 C0wb0y)。
来自此。
要传递数组:
我建议避免数组并使用 std::vector ,它具有更容易理解的复制语义。
What are you trying to accomplish? Do you want to be able to write to the passed in value? Or do you just need to use it? If you want to write to it, the idiomatic way is to pass by reference. If you don't need to write to it, you're best avoiding any risk that you'll write to it accidentally and pass by value. Pass by value will make a copy of the variable for local use. (as an aside, if you don't want to make a copy AND want some level of safety, you can pass by const reference)
Difficult to say. Depends on a lot of things. In both pass by value and pass by reference (or pointer) your making a new primitive type. In pass by value, you're making a copy. In pass by reference/pointer you're passing an address to the original. In the latter case, however, you're requiring an extra fetch of memory that may or may not be cached. Its very difficult to say 100% without measuring it.
That all being said, I doubt the difference is even noticeable. The compiler may be able to optimize out the copy in many pass-by-value cases, as indicated in this article. (thanks Space C0wb0y).
From this.
To pass an array:
I'd recommended avoiding arrays and using std::vector which has more easily understood copy semantics.
如果您关心的是速度,那么通过指针传递原始值可能不值得——然后您就会有“间接”访问该值的开销。
然而,指针通常是“总线的宽度”,这意味着处理器可以一次发送整个值,而不是将值“移位”到总线上发送。因此,指针在总线上的传输速度可能比较小类型(如
char
)更快。这就是为什么旧的 Cray 计算机过去将其char
值设置为 32 位(当时总线的宽度)。It's probably not worth passing primitive values by pointer if your concern is speed -- you then have the overhead of the "indirection" to access the value.
However, pointers often are the "width of the bus", meaning the processor can send the whole value at once, and not "shift" values to send-down-the-bus. So, it is possible pointers are transferred on the bus faster than smaller types (like
char
). That's why the old Cray computers used to make theirchar
values 32 bits (the width of the bus at that time).处理大型对象(例如类或数组)时,传递指针比将整个对象复制到堆栈上更快。例如,这适用于 OOP
When dealing with large objects (such as classes or arrays) passing pointer is faster than copying the whole object onto the stack. This applies to OOP for example
查看您最喜欢的 C++ 教科书,了解有关“输出参数”的讨论。
使用指针作为输出参数而不是引用的一些优点是:
没有令人惊讶的行为,没有远距离操作,调用站点和调用者的语义都很清晰。
与 C 的兼容性(您的问题标题表明这一点很重要)
可由其他语言使用,从共享库或 DLL 导出的函数不应使用仅限 C++ 的功能,例如引用。
Look in your favorite C++ textbook for a discussion of "output parameters".
Some advantages of using a pointer for output parameters instead of a reference are:
No surprising behavior, no action at a distance, the semantics are clear at the call site as well as the caller.
Compatibility with C (which your question title suggests is important)
Usable by other languages, functions exported from a shared library or DLL should not use C++-only features such as references.
您应该很少需要通过指针传递任何内容。如果需要修改参数的值,或者想要防止复制,请按引用传递,否则按值传递。
请注意,防止复制也可以通过复制省略来完成,因此您必须非常小心,不要陷入过早优化的陷阱。这实际上会使您的代码变慢。
You should rarely have to pass anything by pointer. If you need to modify the value of the parameter, or want to prevent a copy, pass by reference, otherwise pass by value.
Note that preventing a copy can also be done by copy-elision, so you have to be very careful not to fall into the trap of premature optimization. This can actually make your code slower.
除了我倾向于牢记的几条规则之外,您的问题没有真正的答案:
char 是 8 个字节,指针是 4 个字节,因此切勿将单个 char 作为指针传递。
像 int 和 float 这样的东西与指针大小相同,但必须引用指针,因此
如果我们使用 pentium i386 汇编器,技术上需要更多时间:
将值加载到 C 中参数“a”的寄存器中,其中是一个 int:
相同的东西,但作为指针传递:
必须取消引用指针需要另一个内存操作,因此理论上(不确定是否在现实生活中)传递指针更长......
之后就是内存问题。如果你想有效地编码所有组合类型(类、结构、数组...)都必须通过指针传递。
想象一下,执行一个类型为 16 字节的递归函数,该函数通过副本传递 1000 次调用,从而在堆栈中生成 16000 字节(您并不真正想要这样,对吗?:))
因此,为了使其简短明了:请看您的类型的大小,如果它比指针大,则通过指针传递它,否则通过副本传递它...
There's is no real answer to your question except few rules that I tend to bare in mind:
char is 8 bytes and a pointer is 4 bytes so never pass a single char as a pointer.
after things like int and float are the same size as a pointer but a pointer has to be referenced so that technically takes more time
if we go to the pentium i386 assembler:
loading the value in a register of a parameter "a" in C which is an int:
the same thing but passed as a pointer:
Having to dereference the pointer takes another memory operation so theorically (not sure it is in real life) passing pointers is longer...
After there's the memory issue. If you want to code effectively everything composed type (class,structure,arrays...) has to be passed by pointer.
Just imagine doing a recursive function with a type of 16bytes that is passed by copy for 1000 calls that makes 16000 bytes in the stack (you don't really want that do you ? :) )
So to make it short and clear: Look at the size of your type if it's bigger than a pointer pass it by pointer else pass it by copy...
按值传递基本类型,并将对象作为 const 引用传递。尽可能避免使用指针。取消引用指针会产生一些开销,并且会使代码变得混乱。比较下面的
factorial
函数的两个版本:调试变得很困难,因为您无法确定对象的值何时何地可能发生变化:
优先使用
vector
类而不是数组。它可以根据需要增大和缩小,并跟踪其大小。访问vector
元素的方式与数组兼容:Pass primitive types by value and objects as
const
references. Avoid pointers as much as you can. Dereferencing pointers have some overhead and it clutters code. Compare the two versions of thefactorial
function below:Debugging becomes hard, as you cannot say when and where the value of an object could change:
Prefer the
vector
class over arrays. It can grow and shrink as needed and keeps track of its size. The wayvector
elements are accessed is compatible with arrays:否,唯一传递非常量引用的情况是函数需要输出参数。
NO, the only time you'd pass a non-const reference is if the function requires an output parameter.