如何在不实际将地址传递给函数的情况下实现'pass by reference'?



我很清楚在C和C++中,所有东西都是按值传递的(即使该值是引用类型)。我认为(但我不是专家)Java也是如此。

所以,这就是为什么我将语言不可知论作为标记,在什么语言中,我可以将任何传递给函数,而不传递一些值?

如果真的存在,这个机制是什么样子的?我仔细思考了一下,但我没有想出任何不涉及传递价值的机制。

即使编译器的优化方式使我在内存中没有一个指针/引用作为真正的变量,它仍然必须计算一个地址作为堆栈(帧)指针的偏移量,并传递它。

有谁能启发我吗?

从C的角度来看:

没有作为语言级别概念的引用。通过用指针指向对象来引用对象。

指针的值是指向对象的地址。指针是按值传递的,就像任何其他参数一样。指向的对象在概念上是通过引用传递的。


至少从C++的角度来看:

"引用传递"是如何实现的[…]?

通常,通过复制对象的地址。

。。。而不实际将地址传递给函数?

如果函数调用是内联扩展的,则无需将地址复制到任何位置。指针也是如此,因为副本可能会由于"好像"规则而被忽略。


在不传递某些值的情况下,用什么语言可以向函数传递任何内容?

这样的语言对函数的概念必须与C有显著的不同。必须没有堆栈帧推送。

函数类C预处理器宏,顾名思义,与函数类似,但它们的参数不会在运行时传递,因为预处理发生在编译之前。

另一方面,您可以拥有全局变量。如果您更改程序的全局状态,并在没有参数的情况下调用函数,则在概念上"将新的全局状态传递给函数",而没有传递任何值。

在机器代码级别,"通过引用传递X"本质上是"通过值传递X的地址"。

指针是值。价值就是价值。值具有唯一标识,需要存储。

引用不是值。引用没有标识。如果我们有:

int x=0;
int& y=x;
int& z=x;

yz都是对x的引用,它们没有独立的身份。

相比之下:

int x=0;
int* py=&x;
int* pz=&x;

pypz都是位于x的指针,并且它们具有独立的身份。你可以修改py而不是pz,你可以得到它们的大小,你可以对它们进行memset。

在某些情况下,在机器代码级别,引用的实现方式与指针相同,只是从未对它们执行某些操作(如重新初始化它们)。

但是C++并不是用机器代码来定义的。它是根据抽象机器的行为来定义的。编译器将代码编译为在这台抽象机器上的操作,这台机器没有固定的调用约定(按照标准),没有引用布局,没有堆栈,没有堆等。然后,它会对此进行任意转换,不会改变行为(常见的是单次赋值),重新排列事物,然后在某个时刻发出汇编/机器代码,在您运行的实际硬件上生成类似的行为

现在,编译C++的几乎通用的方法是编译单元/链接器模型,其中函数被导出为符号,并为其他编译单元提供了一个固定的ABI调用约定来使用它们。然后在链接阶段,将编译单元连接在一起。

在这些ABI中,引用是作为指针传递的。

如何在不实际向函数传递地址的情况下实现"通过引用传递">

在C语言的上下文中,简短的答案是:

  • 在C中,它不是
  • 在C++中,后面跟有"与"号(&)的类型是引用类型。例如,int&是对int的引用。传递参数时对于采用引用类型的函数,对象被真正传递通过引用。(更多信息请访问下面的学术链接。)

但事实上,大多数混淆都是语义。可以帮助解决一些困惑

  • 1)停止使用单词模拟来描述传递地址
  • 2) 停止使用单词引用来描述地址

  • 3)认识到,在C/C++语言的上下文中短语通过引用,单词reference定义为:地址

除此之外,还有许多幻觉概念的例子,它们是为了传达不可能的想法而创建的。无论有多少学术论文或实践讨论,非模仿的概念都可以说是其中之一。

这个(学术论文类别)是另一个在使用C&C++,但世卫组织的结论与现实密切相关。以下是摘录:

。。。不知怎的,这只是编程语言如何实际实现"通过引用传递"的概念的问题:C通过使用指针并将其按值传递给函数来实现这一点,而C++提供了两种实现。从一个方面来说,它重用了从C派生的相同机制(即指针+按值传递)。另一方面,C++还提供了一个本地的"引用传递"解决方案,该解决方案利用了引用类型的思想。因此,即使在C++中,如果您将指针传递给C,也不是真正通过引用传递,而是通过值传递指针(当然,也就是说,除非您将引用传递给指针!例如,int*&)。由于"通过引用传递"这一术语可能存在歧义,因此在使用引用类型时,最好只在C++上下文中使用它。

但正如您和其他人已经注意到的,在通过参数传递任何东西的概念中,无论是还是引用东西根据定义必须具有的值

传递值的意思是传递对象本身

传递指针中,我们将指针的值传递给对象。

逐引用传递中,我们以相同的方式传递引用(基本上是我们知道的指向对象的指针)。

所以,是的,我们总是传递一个值,但问题是这个值是什么?并不总是对象本身。但是,当我们说通过**传递变量时,我们给出的是与要传递的对象相关的信息,而不是实际传递的值。

相关内容

最新更新