代码之家  ›  专栏  ›  技术社区  ›  Naveen

编译器是否优化值传递的函数参数?

  •  18
  • Naveen  · 技术社区  · 14 年前

    假设我有一个函数,其中参数是通过值而不是常量引用传递的。此外,我们假设只有值在函数内部使用,即函数不尝试修改它。在这种情况下,编译器是否能够通过常量引用(出于性能原因)传递值并相应地生成代码?有没有编译器能做到这一点?

    5 回复  |  直到 14 年前
        1
  •  14
  •   Johannes Schaub - litb    14 年前

    如果传递一个变量而不是临时变量,那么如果该变量的复制构造函数在运行程序时做了任何您会注意到的事情,则不允许编译器优化掉该副本(“可观察行为”:输入/输出,或更改可变变量)。

    除此之外,编译器可以自由地做任何它想做的事情(它只需要类似于可观察的行为 仿佛 它根本不会优化)。

    只有当参数是右值(大多数是临时的)时,编译器才允许优化对by-value参数的复制,即使复制构造函数有明显的副作用。

        2
  •  7
  •   kennytm    14 年前

    只有在不导出函数的情况下,编译器才有机会将按引用调用转换为按值调用(或反之亦然)。

    否则,由于调用约定,函数必须保持按值/引用语义的调用。

        3
  •  1
  •   paul    14 年前

    我不知道有任何一般性的保证可以这样做,但是如果被调用的函数是内联的,那么这将允许编译器看到正在进行不必要的复制,如果优化级别足够高,那么复制操作将被取消。GCC至少可以做到这一点。

    您可能需要考虑这个参数值的类是否具有复制构造函数。如果没有,那么pass-by值和pass-by-const-ref之间的性能差异可能是可忽略的。

    另一方面,如果类确实有一个复制构造函数,那么您希望的优化可能不会发生,因为编译器无法删除对构造函数的调用——它不知道构造函数的副作用对您来说并不重要。

    如果您说参数的类是什么,或者它是一个自定义类,那么您可能能够得到更有用的答案,描述它拥有哪些字段,以及它是否有一个复制构造函数。

        4
  •  0
  •   AshleysBrain    14 年前

    在所有的优化中,答案通常是“可能”。检查的唯一方法是检查输出程序集并查看它真正在做什么。如果标准允许,不管它是否真的发生,都取决于编译器的突发奇想。您不应该依赖它的发生,因为代码库中其他地方的任意更改可能会更改优化器使用的启发式方法,这可能会导致它停止执行某个优化。

    注意安全:按照你的意愿进行编码-如果你想要的话,通过引用。但是,如果编写的模板化代码可以处理任何大小的类型,那么选择就不那么明确了。就我个人而言,我赞成传递常量引用-编译器 能够 还可以执行不同的优化,其中可以容纳在引用大小内的小类型通过值传递,而不是通过常量引用传递。但同样,它可能会发生,也可能不会。

        5
  •  -1
  •   Francesco larlin    14 年前

    这篇文章是对这种优化的一个很好的参考: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/