the*_*edi 70 c++ performance function return-value pass-by-reference
我目前正在研究如何编写高效的C++代码,在函数调用方面,我想到了一个问题.比较这个伪代码功能:
not-void function-name () {
do-something
return value;
}
int main () {
...
arg = function-name();
...
}
Run Code Online (Sandbox Code Playgroud)
使用其他相同的伪代码功能:
void function-name (not-void& arg) {
do-something
arg = value;
}
int main () {
...
function-name(arg);
...
}
Run Code Online (Sandbox Code Playgroud)
哪个版本更有效,以及在什么方面(时间,内存等)?如果它取决于,那么第一个什么时候会更有效率,什么时候第二个会更高效?
编辑:对于上下文,此问题仅限于与硬件平台无关的差异,并且大多数情况下也是软件.是否有任何与机器无关的性能差异?
编辑:我不知道这是一个重复.另一个问题是将参考传递(上游代码)与传递值(下图)进行比较:
not-void function-name (not-void arg)
Run Code Online (Sandbox Code Playgroud)
这跟我的问题不一样.我的重点不在于将参数传递给函数的更好方法.我关注的是这是更好的方式来传递出一个结果来自外部范围的变量.
aro*_*ire 24
首先,采取帐户返回一个对象总是比有它引用传递更具可读性(而且在性能上非常相似),因此可能会更有趣的为您的项目返回对象和增加可读性,而无需重要的性能差异.如果您想知道如何获得最低成本,那么您需要返回的是:
如果需要返回简单或基本对象,则两种情况下的性能都相似.
如果对象是如此庞大和复杂,返回它将需要一个副本,它可能比将它作为引用参数慢,但它会花费更少的内存,我认为.
无论如何,你必须考虑编译器做了很多优化,使两个表演非常相似.请参见复制Elision.
嗯,必须明白编译不是一件简单的事情.编译器编译代码时需要考虑很多因素.
人们不能简单地回答这个问题,因为C++标准不提供标准的ABI(抽象二进制接口),因此允许每个编译器编译任何它喜欢的代码,并且每次编译都可以得到不同的结果.
例如,在某些项目中,C++被编译为Microsoft CLR(C++/CX)的托管扩展.既然所有东西都已经有了对堆上对象的引用,我想没有区别.
对于未经管理的编译,答案并不简单.当我想到"XXX会比YYY跑得更快吗?"时会想到几个问题,例如:
std::array)还是指向堆上的东西?(例如std::vector)?如果我举一个具体的例子,我的猜测是在MSVC++和GCC上,std::vector按值返回将是通过引用传递它,因为r值优化,并且会比返回向量快一点(几纳秒)通过移动.例如,对于Clang来说,这可能完全不同.
最终,剖析是唯一真正的答案.
一些答案已经涉及到这一点,但我想根据编辑强调一下
对于上下文,此问题仅限于与硬件平台无关的差异,并且大多数情况下也仅限于软件.是否有任何与机器无关的性能差异?
如果这是问题的限制,答案是没有答案.c ++规范没有规定如何以性能方式实现对象的返回或通过引用的传递,只是它们在代码方面所做的语义.
因此,编译器可以自由地优化一个与另一个相同的代码,假设这不会给程序员带来明显的差异.
鉴于此,我认为最好使用最直观的情况.如果函数确实作为某个任务或查询的结果"返回"了一个对象,则将其返回,而如果该函数正在对外部代码所拥有的某个对象执行操作,则通过引用传递.
你无法概括性能.首先,做一些直观的事情,看看你的目标系统和编译器如何优化它.如果在分析后发现问题,请根据需要进行更改.
这个伪代码函数:
not-void function-name () {
do-something
return value;
}
Run Code Online (Sandbox Code Playgroud)
当返回值不需要对其进行任何进一步修改时,会更好地使用。传递的参数仅在function-name. 不需要更多的参考资料。
其他方面相同的伪代码函数:
void function-name (not-void& arg) {
do-something
arg = value;
}
Run Code Online (Sandbox Code Playgroud)
如果我们有另一种方法来调节同一变量的值,并且我们需要保留通过任一调用对变量所做的更改,那么这将很有用。
void another-function-name (not-void& arg) {
do-something
arg = value;
}
Run Code Online (Sandbox Code Playgroud)