假设我有一个函数,其中参数是按值而不是常量引用传递的。此外,我们假设函数内部仅使用该值,即函数不会尝试修改它。在这种情况下,编译器是否能够确定它可以通过常量引用传递值(出于性能原因)并相应地生成代码?有没有编译器可以做到这一点?
如果您传递变量而不是临时变量,则如果副本构造函数执行了您在运行程序时会注意到的任何操作(“可观察行为”:输入/输出,或更改易失性变量),则不允许编译器优化副本)。
除此之外,编译器可以自由地做它想做的一切(它只需要类似于可观察的行为as-if它根本不会优化)。
仅当参数是右值(最临时)时,编译器才可以优化对按值参数的复制,即使复制构造函数具有可观察到的副作用。
仅当函数未导出时,编译器才有机会将按引用调用转换为按值调用(反之亦然)。
否则,由于调用约定,函数必须保留按值调用/引用语义。
我不知道有任何一般保证可以做到这一点,但是如果被调用的函数是内联的,那么这将允许编译器看到正在进行不必要的复制,并且如果优化级别足够高,复制操作将被消除。 GCC 至少可以做到这一点。
你可能要考虑这个参数值的类是否有复制构造函数。 如果没有,那么按值传递和按常量引用传递之间的性能差异可能可以忽略不计。
另一方面,如果类确实有一个执行某些操作的复制构造函数,那么您希望的优化可能不会发生,因为编译器无法删除对构造函数的调用——它无法知道构造函数的副作用对你来说并不重要。
如果你说出参数的类是什么,或者如果它是自定义类,请描述它有哪些字段以及它是否有复制构造函数,你可能会得到更有用的答案。
经过所有优化,答案通常是“也许”。 唯一的检查方法是检查输出程序集,看看它到底在做什么。 如果标准允许,它是否真的发生取决于编译器的突发奇想。 您不应该依赖它的发生,因为代码库中其他地方的任意更改可能会更改优化器使用的启发式方法,这可能会导致它停止执行特定的优化。
安全起见:按照您的意图进行编码 - 如果您想要的话,可以通过引用传递。 但是,如果您正在编写可以在任何大小的类型上工作的模板化代码,那么选择就不那么明确了。 就我个人而言,我倾向于通过 const 引用传递 - 编译器也可以执行不同的优化,其中可以容纳引用大小的小型类型通过值传递,而不是通过 const 引用传递。 但同样,它可能会发生,也可能不会。