【问题标题】:call by value vs const call by reference按值调用 vs const 按引用调用
【发布时间】:2013-03-11 22:37:50
【问题描述】:

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

【问题讨论】:

标签: c++ reference constants


【解决方案1】:

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

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

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

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

它们是否适用于所有对象尺寸

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

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

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

由于只有其中一个导致了副本,因此该问题有一个明显的答案。

【讨论】:

  • @LuchianGrigore:从技术上讲,您的评论是正确的。但是,我将 OP 的问题解释为“我应该(函数的创建者)对不需要更改值的函数使用传递值还是传递引用 const它的论点”?也许我误解了。将编辑我的答案并澄清,谢谢。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    你的常量引用。

    【讨论】:

      【解决方案4】:

      我想你的意思是:

      void Fn1(MyType x);
      

      void Fn2(const MyType& x);
      

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

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

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

      以下是您问题的答案:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 2021-04-25
          • 2013-08-15
          • 1970-01-01
          • 1970-01-01
          • 2021-08-24
          • 2014-02-09
          • 2013-12-15
          • 2015-06-07
          相关资源
          最近更新 更多