简体   繁体   English

传递引用的开销是多少?

[英]what is the overhead of passing a reference?

how expensive is it to access a member variable when the getter in question return a reference? 当有问题的getter返回引用时访问成员变量有多贵?

for example, if you have a class that needs to use such an accessor fairly often, how much more efficient would it be to store said reference in the class that needs to use it and simply initialise it once? 例如,如果你有一个需要经常使用这种访​​问器的类,那么将所述引用存储在需要使用它的类中并简单地初始化一次会有多高效?

Get functions generally shouldn't return references. 获取函数通常不应返回引用。 The reason for this is that it makes the member available to the public - if you want to do this just make it a public member. 这样做的原因是它使该成员对公众开放 - 如果你想这样做只是让它成为一个公共成员。

class foo {
  int bar;
  public:
    int& get_bar() { return bar; } // this is silly! Just make bar public!
}

Anyway, if it's as simple as get_bar it will be inlined to something akin to foo.bar . 无论如何,如果它像get_bar一样简单,它将被内联到类似于foo.bar As Oli noted, you could also make it a const reference, although for small types like int you should go ahead and return by value. 正如Oli指出的那样,你也可以将它作为const引用,尽管对于像int这样的小类,你应该继续并按值返回。

With more expensive types, references start to be beneficial. 对于更昂贵的类型,参考开始是有益的。 You can assume that: 你可以假设:

  • Value's 'overhead' is based on size of what you're returning 价值的“开销”基于您返回的大小
  • Reference's 'overhead' is based on size of reference and cost to dereference 参考的“开销”基于参考的大小和解除引用的成本

Eg: 例如:

foo x;
x.get_value().func(); // calls copy constructor at least once and destructor
x.get_reference().func(); // may require dereference when using

Regarding complexity, returning or passing a reference is just like passing a pointer. 关于复杂性,返回或传递引用就像传递指针一样。 Its overhead is equivalent to passing an integer the size of a pointer, plus a few instructions . 它的开销相当于传递一个指针大小的整数,加上一些指令 In short, that is as fast as is possible in nearly every case. 简而言之,几乎在所有情况下都尽可能快。 Builtin types (eg int, float) less than or equal to the size of a pointer are the obvious exception. 小于或等于指针大小的内置类型(例如int,float)是明显的例外。

At worst, passing/returning a reference can add a few instructions or disable some optimizations. 在最坏的情况下,传递/返回引用可以添加一些指令或禁用某些优化。 Those losses rarely exceed the costs of returning/passing objects by value (eg calling a copy constructor + destructor is much higher, even for a very basic object). 这些损失很少超过按值返回/传递对象的成本(例如,调用复制构造函数+析构函数要高得多,即使是非常基本的对象)。 Passing/returning by reference is a good default unless every instruction counts, and you have measured that difference. 除非每条指令都有效,否则通过引用传递/返回是一个很好的默认值,并且您已经测量了这种差异。

Therefore, using references has incredibly low overhead. 因此,使用引用具有令人难以置信的低开销。

One can't really quantify how much faster it would be without knowing the complexity of your types and their constructor/destructor, but if it is not a builtin type, then holding a local and returning it by reference will be fastest in most cases - it all depends on the complexity of the object and its copy, but only incredibly trivial objects could come close the speed of the reference. 如果不知道类型及其构造函数/析构函数的复杂性,就无法真正量化它速度,但如果它不是内置类型,那么在大多数情况下,持有本地并通过引用返回它将是最快的 -这一切都取决于对象及其副本的复杂程度,但只有令人难以置信的微不足道的对象才能接近引用的速度。

If the function definition is available and is relatively simple, then such a function is getting inlined and there is no overhead whatsoever compared to accessing a member directly. 如果函数定义可用并且相对简单,那么这样的函数将被内联,并且与直接访问成员相比没有任何开销。 Otherwise the sequence of operations is as simple as getting the address a class/structure object, applying an offset to get an address of the member, and returning this address to the caller. 否则,操作序列就像获取地址类/结构对象,应用偏移量来获取成员的地址,以及将此地址返回给调用者一样简单。 Now, for those cases it makes sense to return by reference only if object is non-copyable or its size is greater than the size of a pointer. 现在,对于这些情况,仅当对象是不可复制的或者其大小大于指针的大小时才通过引用返回是有意义的。 The reason for non-copyable objects is obvious, otherwise you look at copying overhead - size of structure versus size of a pointer. 不可复制对象的原因是显而易见的,否则你会看到复制开销 - 结构的大小与指针的大小。 So the rule of thumb is this - return large objects by reference (or pointer), and small objects (integers, doubles, etc.) by copying them. 所以经验法则是这样 - 通过引用(或指针)返回大对象,通过复制它们返回小对象(整数,双精度等)。 And in those cases where you do not have to control access rights to members trough-out your program - simply use structures with public access to members and do not bloat your code with tons of getters and setters. 在那些您无需控制成员访问权限的情况下 - 只需使用具有公共访问权限的成员的结构,并且不要使用大量的getter和setter来破坏您的代码。

Frankly, if you start wondering about this overhead: have you already thought about calling conventions, using stdcall instead of cdecl? 坦率地说,如果你开始想知道这个开销:你有没有想过调用约定,使用stdcall而不是cdecl?

The amount of speed you gain from that is similar to what you're talking about when discussing this. 你从中获得的速度类似于你在讨论时所说的速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM