传递const值或const ref之间的编译器视角的差异

时间:2014-08-23 09:10:21

标签: c++ parameter-passing

在c ++的上下文中。

我想知道它之间的区别是什么:

T f(T const val);

和此:

T f(T const & val);

我知道一个是值传递,但是,从编译器的角度来看,这是一个不会改变的值,所以我的问题是:

  1. 在const值参数传递的情况下,编译器是否仍然需要复制?
  2. 哪一个更适合编译器的优化器以及为什么?

3 个答案:

答案 0 :(得分:1)

假设如下:

launch_service(const Configuration); // launches service in a different thread

Configuration config;

launch_service(config);
config.set("key", "value");

如果引用Configuration,则在单独的线程中运行的服务可能会读取后面添加的配置设置key。如果按值获取(如示例中所示),则无法反映其他线程以后所做的更改。

这意味着,取一些const valueconst ref是不同的,编译器必须在前者中创建一个副本。

答案 1 :(得分:1)

示例1:

T f(T const val);

如果编译器无法内联(或以其他方式修改函数f),则必须复制T并将其传递给fconst与调用代码的视角没有区别,只在函数f内部。

示例2:

T f(T const & val);

编译器将val的地址传递给函数,因此不需要复制。

但是,使用小/简单类型的引用会导致额外的开销,因为参数作为元素的地址传递,f的内容必须进行额外的操作才能加载地址然后加载val的实际内容。因此,问题是“复制T有多复杂,f使用val”确定最有效的函数有多复杂。总是,如果您想要获得更好的性能,请测量结果!

最后,如果编译器能够内联代码,它可能会消除对象的所有副本(假设构造函数已知并且不会阻止被删除 - 例如,将I / O添加到构造函数将阻止它被淘汰了)。

答案 2 :(得分:0)

关于

  

const值参数传递的情况下,编译器是否仍需要复制?

是的,程序必须表现为,好像一样。

在实践中,可以传递一个地址,然后该函数可以自己制作一个副本,如果有必要的话(因为调用了其他函数)。

请注意,正式参数的顶级const将被忽略为函数类型;它只影响函数的实现,如果它存在于实现的函数头中。

  

哪一个更适合编译器的优化器以及为什么?

在很大程度上取决于机器代码内联的类型,该值是否将存储在调用后可访问的某个位置,以及是否使用整个程序优化。简而言之,这取决于。作为一般规则,如果您认为可能存在效率问题,则衡量