3

我对按值调用和按引用调用 const 之间的区别有点困惑。有人可以向我解释一下吗。例如,它们是否都可以防止更改调用者参数,它们是否适用于所有对象大小,是否复制参数而一个不复制参数,以及在复制时使用更多内存?

4

5 回答 5

7

它们是否都可以防止更改调用者参数

按值传递会创建调用者提供的参数的副本,因此无论函数做什么,它都会在单独的对象上执行。这意味着永远不会触及原始对象,因此在这种情况下,答案是“”。

const另一方面,通过引用传递,让函数引用调用者提供的同一个对象,但它不会让该函数修改它......除非(正如 Luchian Grigore 在评论中正确指出的那样)函数的实现者使用从引用const_cast<>中丢弃const-ness,只有在知道绑定到引用的对象声明为const类型时才能安全地完成此操作(否则,您将获得未定义的行为)。

由于考虑到您的问题,这似乎不是最有可能的情况,并且考虑到通常接受对 的引用const表示不会触及该论点的承诺,那么答案是,只要我们假设这个承诺是满足,通过引用传递const不会改变调用者提供的参数。所以答案再次是“”——我上面提到的一点警告。

它们对所有物体大小都快吗

,尽管您应该首先定义“快速”。如果要传递的对象的类型复制起来(或移动,如果执行的是移动而不是复制)代价高昂,那么按值传递可能会很慢。无论您传递的值的类型是什么,通过引用传递总是会花费相同的成本(地址的大小)。

请注意,在某些体系结构和某些数据类型(如char)上,按值传递可能比按引用传递更快,而对于足够大的 UDT,情况通常相反。

制作副本时哪个使用更多内存?

由于其中只有一个导致复制,因此问题有一个明显的答案。

于 2013-03-11T22:41:32.400 回答
0

按值调用将复制它确实保护调用者参数的对象的所有元素,因为如果您要更改某些内容,它只是您正在更改的副本。
通过 const 引用调用不会复制元素,但由于“const”,它将保护调用者的参数。

你 const 参考。

于 2013-03-11T22:42:22.600 回答
0

主要区别在于通过const引用(或非常量)传递不会复制参数。(副本实际上会受到复制省略,但理论上它是在您通过值传递时传递给函数的副本)

在某些情况下,按值传递同样快,甚至更快(通常当对象最多为寄存器大小时)。您通常会通过值传递基本类型,并通过引用传递类类型。

通过const引用传递时,您仍然可以通过将 const 强制转换(通过const_cast)来修改原始值,但如果原始值为 .,则会导致未定义的行为const

于 2013-03-11T22:40:38.997 回答
0

我想你的意思是:

void Fn1(MyType x);

void Fn2(const MyType& x);

在前一种情况下,始终会创建对象的副本,这会使其速度变慢,尤其是在类型具有非平凡构造函数的情况下。原始对象将不受函数内对副本所做的任何更改的影响,但副本本身可以更改。

后一个示例不会创建副本,并且通常会更快。在函数内部,只能在参数上调用 const 函数(除非您使用诸如丢弃 const 之类的肮脏技巧),从而保证不会修改对象。

重要提示:本讨论不涉及具有特殊语义的类型,例如智能指针。在这种情况下,按值调用仍然允许您更改逻辑上相同的对象,即不是智能 ptr 实例本身,而是它指向的对象。

因此,这里是您的问题的答案:

  • 它们是否都可以防止更改调用者参数:是的,原始对象将保持不变(不包括技巧)
  • 它们是否对所有对象大小都快:它们不是同样快 - 通过引用调用通常更快,除了一些速度或多或少相同甚至可能稍微快一点的原始类型,具体取决于编译器优化。
  • 要么复制参数,而不要复制参数:按值调用创建副本,按引用调用不会
  • 制作副本时哪个使用更多内存?引用调用不会创建副本,因此答案很明确
于 2013-03-11T22:47:35.593 回答
0

另一点值得一提的是,引用调用函数被转换为内联函数。

于 2019-04-03T22:11:13.740 回答