传递参考的开销是多少?
Posted
技术标签:
【中文标题】传递参考的开销是多少?【英文标题】:what is the overhead of passing a reference? 【发布时间】:2012-01-05 06:16:01 【问题描述】:当有问题的 getter 返回一个引用时,访问一个成员变量的成本是多少?
例如,如果您有一个类需要经常使用这样的访问器,那么将所述引用存储在需要使用它的类中并简单地初始化一次会更有效吗?
【问题讨论】:
如果您在标记为 [coding-style] 的问题中询问性能开销... 开销与什么相比? 与将引用变量存储在类中并引用它相比。我确实在问题中说过。 【参考方案1】:关于复杂性,返回或传递引用就像传递指针一样。它的开销相当于传递一个指针大小的整数,加上一些指令。简而言之,几乎在所有情况下都尽可能快。小于或等于指针大小的内置类型(例如 int、float)是明显的例外。
在最坏的情况下,传递/返回引用可以添加一些指令或禁用一些优化。这些损失很少超过按值返回/传递对象的成本(例如,调用复制构造函数 + 析构函数要高得多,即使对于非常基本的对象也是如此)。通过引用传递/返回是一个很好的默认值,除非每条指令都很重要,并且您已经测量了这种差异。
因此,使用引用的开销非常低。
在不知道类型及其构造函数/析构函数的复杂性的情况下,无法真正量化它的速度会有多少,但如果它不是内置类型,则持有一个本地类型并返回在大多数情况下,通过引用将是最快的 - 这完全取决于对象及其副本的复杂性,但只有非常琐碎的对象才能接近引用的速度。
【讨论】:
【参考方案2】:Get 函数通常不应返回引用。这样做的原因是它使该成员可供公众使用 - 如果您想这样做,只需将其设为公共成员即可。
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
【讨论】:
您可以随时返回const int &
。但更重要的一点仍然是,它将内部与接口耦合在一起。 (不过我不会为此 +1,因为它没有回答问题......)
虽然我大体上同意这种观点,但有正当理由返回参考资料。 std::complex 可能是一个值得注意的例子,因为低级访问目前只能通过使用 reinterpret_cast 的标准获得/保证(这不是很好的做法,也不是 constexpr 友好的)。请注意 std::memcpy 和 std::bit_cast 不返回引用,因此它们不能用于修改基础数据。但是 std::complex 本身就有问题。设计良好的 API 看起来不像 std::complex。【参考方案3】:
如果函数定义可用并且相对简单,那么这样的函数就是内联的,与直接访问成员相比没有任何开销。否则,操作序列就像获取类/结构对象的地址一样简单,应用偏移量来获取成员的地址,然后将此地址返回给调用者。现在,对于这些情况,仅当对象不可复制或其大小大于指针的大小时,才有意义通过引用返回。不可复制对象的原因很明显,否则您会查看复制开销 - 结构的大小与指针的大小。所以经验法则是这样的——通过引用(或指针)返回大对象,通过复制返回小对象(整数、双精度等)。在那些你不必通过你的程序控制成员访问权限的情况下——只需使用对成员有公共访问权限的结构,不要用大量的 getter 和 setter 来膨胀你的代码。
【讨论】:
【参考方案4】:坦率地说,如果您开始怀疑这种开销:您是否已经考虑过调用约定,使用 stdcall 而不是 cdecl?
您从中获得的速度与您在讨论此问题时所谈论的内容相似。
【讨论】:
我对此一无所知,您能详细说明一下吗? msdn.microsoft.com/en-us/library/984x0h58.aspx msdn 上的那篇文章展示了不同的调用约定。您应该首先阅读有关 thsoe 的信息,google 上有很多信息。但我想说的是,想知道这只是过早的优化。以上是关于传递参考的开销是多少?的主要内容,如果未能解决你的问题,请参考以下文章