【问题标题】:Is a function call parameter always a new object?函数调用参数总是一个新对象吗?
【发布时间】:2013-11-14 03:46:51
【问题描述】:

我读到了:

在Java中,所有参数都是按值传递的。在 C++ 中,参数可以 路过:

value,
reference, or
const-reference

但是,如果我将一个指针传递给一个函数并在该函数中更改指针,这不会更改对象,其标识符用于将其指定为参数,它只会更改传递给函数的指针.

这实际上意味着从技术上讲,在 C++ 中,所有内容都是通过值作为副本传递的,不同之处在于这个复制的值可以用作内存地址(指针或引用),所以如果我想修改传递的现有指针作为函数参数,我必须传递其内存地址的值,而不是该指针持有的内存地址的值。

那么假设每个函数参数都是从现有对象派生的新副本,该对象专门创建用于在单个特定调用中用作参数,而从来没有一个实际的预先存在的对象是正确的?

【问题讨论】:

  • 是的,这在技术上是正确的。从语义上讲,传递引用(如int&)可能被认为是不同的。但是实际在 CPU 上执行的代码仍然在压一个不能改变的内存地址。
  • 按引用传递在语义上与按值传递指针有很大不同。按值传递指针需要显式获取某物的地址才能获得要传递的指针;在函数内部,您需要取消引用它以对指向的事物执行操作。通过引用传递,你不会做任何这些事情——你传递一些东西就像传递值一样,在函数内部你对参数进行操作就像对一个值进行操作一样。不要混淆这两个。

标签: c++ copy parameter-passing


【解决方案1】:

在Java中,所有参数都是按值传递的。

这有点误导,因为当对象引用按值传递时,并且对象支持突变,调用者可以更改传入的对象,有效地使其看起来像按引用传递。

这实际上意味着从技术上讲,在 C++ 中,所有内容都是通过值作为副本传递的,不同之处在于这个复制的值可以用作内存地址(指针或引用),所以如果我想修改传递的现有指针作为函数参数,我必须传递其内存地址的值,而不是该指针持有的内存地址的值。

这个评估是正确的。通过指针传递和通过引用传递仍然会在被调用函数的空间中创建一个副本,至少在逻辑上是这样:

  • 当按值传递对象时,会创建对象本身的副本
  • 通过指针传递对象时,会创建指针的副本
  • 通过引用传递对象时,会创建引用的副本

简而言之,传递给调用者的任何内容都是按值传递的。有时,传递的值可用于修改原始对象。

当您考虑优化和内联时,事情开始变得更加混乱:可能没有创建指针或引用的副本,但整体逻辑保持不变。

【讨论】:

  • “有效地使它看起来像通过引用传递。”不。有很大的不同。
  • @newacct 介意更具体吗?我想我在什么意义上说得很具体,这让它看起来像是通过裁判,所以直截了当地说“不”并不完全公平,不是吗?
  • 按值传递和按引用传递在处理传递的变量时具有非常具体的语义含义。如果它是一个指针,它与变量指向的对象无关。 Java只有值传递。试图混淆差异是很多人对此感到困惑的原因。
  • @newacct 有些人对此感到困惑的最大原因是,在Java 中,对象引用是按值传递的。在这种安排中指出与通过引用传递的相似之处绝对没有错。
【解决方案2】:

这实际上意味着从技术上讲,在 C++ 中,所有内容都是通过值作为副本传递的,不同之处在于这个复制的值可以用作内存地址(指针或引用)

是的,您的假设在技术上是正确的,几乎适用于所有常见的编程语言。为什么? 您应该注意通过引用传递 是一种软件抽象。 CPU 真正做的是(当然这取决于函数调用约定,我正在简化事情)是将数据复制到寄存器中。

为了模拟您正在使用相同的值,您所做的(以及大多数常见语言所做的)是传递原始数据的内存地址,换句话说,是一个指针。 这就是 C 模拟通过引用传递所做的,这就是 C++ 所做的(引用实际上是指针),这就是 Java 所做的。

【讨论】:

    【解决方案3】:

    传递给函数的确实是一个独特的对象。但是,如果我们有object X,然后我们引用object& Y = X;,然后是object& Z = X;,那么我们就有了三个“对象”——X,其类型为object,以及Y和@ 987654327@ 是对object 的类型引用。 object 仍然只有一个“真实”实例 - YZ 都引用相同的 X

    同样,如果我们传递对函数的引用:

    void func(object& R)
    {
      ...
    }
    

    func(X);
    

    该函数将接收一个引用 X 的对象 - 这使得该函数看起来好像它实际上正在修改 X,因为这就是引用的工作方式 - 引用的实际值是指的东西原始对象。

    我想说的是“传递给函数的所有内容都是唯一的对象,但在引用的情况下它可能指的是同一个原始对象”。

    在 C++ 中,指针和引用非常相似,除了以下两点: 1. 引用只能对特定对象初始化一次 - 并且只能以实际引用对象的方式创建,不能有引用“无”或“不是”的引用尚未设置”[但是,您可以拥有“陈旧”的引用,其中最初引用的对象不再存在]。 2. 引用使用与基本对象相同的语法,例如r.member = 42;,其中指针使用*pp->member = 42; 来“获取”对象的内容。

    [是的,完全有可能在 C++ 规范中定义一个编译器,其中指针和引用“在内部不是一回事”,但到目前为止我从未见过一个]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-11
      • 2011-04-25
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-15
      • 1970-01-01
      相关资源
      最近更新 更多