繁体   English   中英

传递引用的开销是多少?

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

当有问题的getter返回引用时访问成员变量有多贵?

例如,如果你有一个需要经常使用这种访​​问器的类,那么将所述引用存储在需要使用它的类中并简单地初始化一次会有多高效?

获取函数通常不应返回引用。 这样做的原因是它使该成员对公众开放 - 如果你想这样做只是让它成为一个公共成员。

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

无论如何,如果它像get_bar一样简单,它将被内联到类似于foo.bar 正如Oli指出的那样,你也可以将它作为const引用,尽管对于像int这样的小类,你应该继续并按值返回。

对于更昂贵的类型,参考开始是有益的。 你可以假设:

  • 价值的“开销”基于您返回的大小
  • 参考的“开销”基于参考的大小和解除引用的成本

例如:

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

关于复杂性,返回或传递引用就像传递指针一样。 它的开销相当于传递一个指针大小的整数,加上一些指令 简而言之,几乎在所有情况下都尽可能快。 小于或等于指针大小的内置类型(例如int,float)是明显的例外。

在最坏的情况下,传递/返回引用可以添加一些指令或禁用某些优化。 这些损失很少超过按值返回/传递对象的成本(例如,调用复制构造函数+析构函数要高得多,即使是非常基本的对象)。 除非每条指令都有效,否则通过引用传递/返回是一个很好的默认值,并且您已经测量了这种差异。

因此,使用引用具有令人难以置信的低开销。

如果不知道类型及其构造函数/析构函数的复杂性,就无法真正量化它速度,但如果它不是内置类型,那么在大多数情况下,持有本地并通过引用返回它将是最快的 -这一切都取决于对象及其副本的复杂程度,但只有令人难以置信的微不足道的对象才能接近引用的速度。

如果函数定义可用并且相对简单,那么这样的函数将被内联,并且与直接访问成员相比没有任何开销。 否则,操作序列就像获取地址类/结构对象,应用偏移量来获取成员的地址,以及将此地址返回给调用者一样简单。 现在,对于这些情况,仅当对象是不可复制的或者其大小大于指针的大小时才通过引用返回是有意义的。 不可复制对象的原因是显而易见的,否则你会看到复制开销 - 结构的大小与指针的大小。 所以经验法则是这样 - 通过引用(或指针)返回大对象,通过复制它们返回小对象(整数,双精度等)。 在那些您无需控制成员访问权限的情况下 - 只需使用具有公共访问权限的成员的结构,并且不要使用大量的getter和setter来破坏您的代码。

坦率地说,如果你开始想知道这个开销:你有没有想过调用约定,使用stdcall而不是cdecl?

你从中获得的速度类似于你在讨论时所说的速度。

暂无
暂无

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

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