函数调用参数总是一个新对象吗?

时间:2013-11-03 11:06:08

标签: c++ copy parameter-passing

我读到了:

  

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

value,
reference, or
const-reference

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

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

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

3 个答案:

答案 0 :(得分:4)

  

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

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

  

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

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

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

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

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

答案 1 :(得分:1)

  

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

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

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

答案 2 :(得分:0)

传递给函数的内容确实是一个独特的对象。但是,如果我们有object X,我们会参考object& Y = X;,然后object& Z = X;,那么我们有三个“对象” - X,其类型为{{ 1}},以及objectY,它们是Z的类型引用。仍然只有一个object - objectY的“真实”实例都引用相同的Z

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

X

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

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

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

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

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