首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++函数的效率?

C++函数的效率?
EN

Stack Overflow用户
提问于 2013-11-26 10:25:22
回答 3查看 96关注 0票数 0

这可能是一个简单的问题,但这是我的想法。这是关于以下两个函数之间的差异:

代码语言:javascript
复制
T func_one(T obj) {      //for the purpose of this question, 
    return obj + obj;    //T is a large object and has an overloaded '+' operator 
}

T func_two(T obj) {
    T output = obj + obj;
    return output;
}

func_one()中,我不需要创建一个对象T,给它赋值,然后返回对象,只需要返回值本身,而不创建新对象。如果T是一个大对象,当返回两个对象的总和时,func_one()是否会比func_two()更有效,或者func_one()会不会让对象变成T

EN

回答 3

Stack Overflow用户

发布于 2013-11-26 10:27:49

编译器会将fund_two优化成类似于func_one的东西,然后再优化成其他东西,长话短说,你不需要担心这个,除非你真的需要担心这个,在这种情况下,你可以查看asm的输出。

票数 0
EN

Stack Overflow用户

发布于 2013-12-30 18:49:50

Short answer:我们无法知道

Long answer:这在很大程度上取决于T的工作方式以及您的编译器对返回值优化的支持。

任何按值返回的函数都可以应用RVO或NRVO优化。这意味着它将直接将返回值构造到调用函数中,省去了复制构造函数。由于这是按值返回大对象的问题,这将意味着性能的大幅提高。

func_one和func_two之间的不同之处在于,func_one返回一个匿名临时值,即一个r值;这意味着可以很容易地使用RVO。func_two返回一个命名值,一个l值,因此将使用NRVO,这是一种更难的优化。然而,func_two是微不足道的,所以它几乎肯定会应用NRVO,并且这两个函数基本上是相同的。

这是假设你有一个现代甚至半现代的编译器;如果没有,这将在很大程度上取决于你如何实现T。

如果T具有移动语义,那么您的编译器将能够移动而不是复制。这应该适用于这两个函数,因为这两个函数中都存在临时函数;但是,由于func_two返回一个命名值,因此它可能无法使用移动语义。这取决于编译器,如果编译器不执行RVO或NRVO,我怀疑它是否在执行move。

最后,这取决于如何实现+运算符和=运算符。例如,如果它们是作为表达式模板实现的,那么fun_two仍然需要赋值,这会减慢它的速度,而as func_one将只返回一个高度优化的临时变量。

摘要中的在几乎所有的实际环境中,这些都是相同的。在编译器行为非常奇怪的小窗口中,func_one几乎普遍更快。

票数 0
EN

Stack Overflow用户

发布于 2013-12-30 19:15:56

现代编译器可以将有额外变量的版本转换为没有额外变量的版本(名为返回值优化,这在这里是一个相当常见的问题来源,例如Why isn't the copy-constructor called when returning LOCAL variable )。所以这不是你应该担心的开销。

你应该担心的开销是函数调用的开销。一个加法最多只需要一个现代CPU一个周期。函数调用需要10到20个周期,具体取决于参数的数量。

我有点不确定你的问题中的T是什么意思(它是一个模板参数吗?它是一个类吗?它是否是您不想在问题中透露的类型的占位符?)但是,是否存在函数调用开销问题取决于该类型。这取决于你的编译器是否能内联你的函数。

  • 显然,如果它是内联的,则没有函数调用开销。
  • 如果T是具有开销很大的operator+()重载的复杂类型,那么您也很好。但是,
  • ,如果T是<代码>D11,而您的函数没有内联,则函数中大约有90%的开销。<代码>H212<代码>F213
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20207397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档