是通过引用自动传递函数的常量参数

Are const arguments of function are passed by reference automatically?

本文关键字:传递函数 常量 参数 引用      更新时间:2023-10-16

如果我有如下代码:

void foofunc(const int fooarg)
{
    // something here
}

fooarg是通过值传递还是通过引用传递?由于fooargconst,它不会被修改,所以如果通过引用传递也没关系。


如果我有一个代码,看起来如下:

void foofunc(int fooarg)
{
    // something here, but fooarg is not gonna get modified
}

fooarg是通过值传递还是通过引用传递,它是常量还是常量?情况同上。它不会被修改。

声明说它是通过值传递的。所以它是通过值传递的。

它是按值传递的,因为声明说它是按价值传递的。

它不会被修改,所以如果通过引用传递它是可以的。

不是这样,但不是这样。另一个线程可能会修改传递的变量。在这种情况下,通过引用传递会改变语义。

函数签名中忽略了顶级const,因此这些声明完全等效:

void foofunc(const int fooarg);
void foofunc(int fooarg);

因此,两者的语义都是按值传递的。当然,编译器可以按照"好像"规则对此进行优化,因此只要有足够的信息,就可以使用引用语义。

在语言级别,如果按值传递,那么它当然是按值传递的,而不是通过引用传递的。但是,传递是如何在引擎盖下物理实现的,这是一个实现细节,并不像第一眼看到的那样依赖于参数const

在许多编译器实现中,通过值传递的"大"参数(从语言角度来看)实际上是通过引用在引擎盖下传递的,然后由函数本身的序言代码进行复制。函数体使用副本,通过值创建正在接收的参数的结束效果。

在其他实现中,参数实际上是"按值"传递的,即副本是由调用者预先准备的。

前一种方法的优点是,编译器知道函数的内部工作原理,当它知道不需要复制时(例如,当函数体没有试图修改参数值时),可能会决定不进行复制。请注意,无论相应的参数是否声明为const,智能编译器都可以执行此分析并消除不必要的复制。

这是一个优化代码生成的问题,不受语言规范的约束。然而,这些问题可能由依赖于平台的ABI规范指定。