假设我有一个函数,其中参数是通过值而不是const-reference传递的。此外,假设在函数内部仅使用该值,即函数不尝试修改它。在这种情况下,编译器是否能够确定它可以通过const-reference传递值(出于性能原因)并相应地生成代码?是否有任何编译器可以做到这一点?
答案 0 :(得分:14)
如果你传递一个变量而不是一个临时变量,如果它的复制构造函数执行了你在运行程序时会注意到的任何事情(“可观察行为”:输入/输出或更改),则不允许编译器优化掉副本。易变量)。
除此之外,编译器可以自由地执行它想要的一切(它只需要类似于可观察的行为 as-if 它根本就没有优化)。
仅当参数是rvalue(大多数临时)时,即使复制构造函数具有可观察的副作用,也允许编译器将副本优化为by-value参数。
答案 1 :(得分:7)
只有在未导出函数的情况下,编译器才有可能将call-by-reference转换为call-by-value(或反之亦然)。
否则,由于调用约定,函数必须保持call-by-value / reference语义。
答案 2 :(得分:1)
我不知道有任何一般保证会这样做,但如果被调用的函数被内联,那么这将允许编译器看到正在进行不必要的复制,并且如果优化级别高足够的,复制操作将被消除。海湾合作委员会至少可以这样做。
您可能想要考虑此参数值的类是否具有复制构造函数。如果没有,那么pass-by-value和pass-by-const-ref之间的性能差异可能是可以忽略不计的。
另一方面,如果类确实有一个复制构造函数来做东西,那么你希望的优化可能不会发生,因为编译器无法删除对构造函数的调用 - 它无法知道副作用构造函数对你来说并不重要。
如果你说参数的类是什么,或者它是一个自定义类,你可能能得到更多有用的答案,描述它有哪些字段以及它是否有一个复制构造函数。
答案 3 :(得分:0)
通过所有优化,答案通常是“可能”。唯一的检查方法是检查输出组件并查看它的确实做了什么。如果标准允许它,无论它是否真的发生都归结为编译器的奇思妙想。您不应该依赖它发生,因为代码库中其他地方的任意更改可能会更改优化程序使用的启发式方法,这可能会导致它停止执行某个优化。
安全地玩耍:按照您的意图编写代码 - 如果您想要的话,可以通过引用传递。但是,如果您正在编写可以在任何大小的类型上工作的模板化代码,那么选择就不那么明确了。我个人认为传递const引用 - 编译器可能也执行不同的优化,其中一个可以适合引用大小的小类型通过值传递,而不是通过const引用传递。但同样,它可能会发生,也可能不会发生。
答案 4 :(得分:-1)
这篇文章是对这种优化的极好参考: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/