"引用传递"中的术语"引用"的起源是什么?

13

Java/C#程序员常说他们的语言是按值传递引用,这意味着“引用”是一个对象指针,在调用函数时会被复制。

而在C++中(以及Perl和PHP的更动态形式中),引用是对其他名称或运行时值的别名。

我对这里的词源学很感兴趣。这个术语最早是如何使用的?让我们从Java之前开始看起,不过如果您知道C++之前的用法,那也会让我感兴趣。

(我知道词汇会发生变化等事实,但我只是对历史感兴趣。)

9个回答

15
在1973年3月Richard E Fairley的论文"Semantic Models of Parameter Passing"中,早期使用了术语“按引用调用”。
在早期,术语是不一致的。例如,Fortran 66规范使用了“按名称关联”和“按值关联”这些短语。我们现在称之为“按引用调用”和“按值调用”。相比之下,Algol 60规范(1962年)使用了“按名称调用”和“按值调用”这些术语...而这两个术语都不是我们目前所说的按引用调用。 编辑:对于那些想要将指定Fortran 66规范的先驱标记为混乱的人,考虑一下这个:
  1. Fortran 66是第一次尝试使用(我们现在称之为)按引用调用的语言进行规范。

  2. 这是仅有的第二次尝试指定支持参数传递的子程序的语言。

  3. Fortran 66的“按名称关联”可以被视为Algol 60的“按名称调用”的受限(退化)形式。这种限制在于,在Fortran中,名称必须是一个简单的变量或数组名称,而在Algol 60中可以是任何表达式。

  4. 当时(1966年),并不清楚Algol 60的“按名称调用”注定要被放弃作为一个坏主意。事实上,当我在1977年作为本科生学习Algol 60时,我不记得讲师将“按名称调用”作为一个坏主意呈现出来。(它被呈现为难以理解...但那是另一回事。)


“按名称关联”是一个引用(听起来像是别名),还是Algol风格的传值调用(在另一个答案中描述了各种奇怪的情况)? - Paul Biggar
@Paul - 正如我所说,现在我们称之为“按引用传递”。请查看链接的规范。 - Stephen C
2
函数式编程语言仍然使用“按名称调用”和“按值调用”这些术语,以及另一种分类:“按需调用”(例如Haskell)。 - Daniel Spiewak
好的发现!但我不会说“不一致”,这有点混淆。似乎不同的人一贯选择不同的术语,但知道它们指的是相同的术语,“按引用调用”(或“按引用传递”)胜过“关联”。 - Andrew Dalke
不一致 != 困惑。我只是在说还没有达成共识。 - Stephen C
在ALGOL 60中,按名称调用绝对不是按引用调用。请阅读Jensen's Device。(谷歌是你的朋友。) - John R. Strohm

11

(此回复仅适用于C#,据我所知)

不要告诉Eric Lippert引用就是指针;-p在MS C# / .NET中它们恰好是相同的东西,但这是一种实现细节。引用是一种不透明、安全的“东西”,允许您定位对象。指针是一个内存地址。他们努力确保您始终知道自己的意思...

完全可以实现一个CLI和编译器,不将两者视为相同;尽管如此,您仍然会传递一个引用到该值。

引用不是地址


有趣。我相信Java参考手册在某些地方称它们为指针 - 我更熟悉Java的情况。 - Paul Biggar
Eric Lippert 的链接很棒! - Alex
4
指针不是内存地址。指针通常是内存地址,但它不等同于内存地址。例如,在有分段存储器的系统中,指针可能是一个偏移量(“near” pointers),或者是一个选择器加上一个偏移量(“far” pointers)。根据定义,C# 指针具有与指针相同的操作语义。指针是可以被重新绑定的引用,而这正是 C# 所具备的。 - DrPizza
@DrPizza - 嗯...这说明了我对此的了解有限。好吧,我会将“原样保留”作为与引用和内存地址相关的注释,但是我已经注意到了你的观点。我需要深入研究定义才能尝试挑战它,所以我会假设它是正确的。 - Marc Gravell

3

我认为历史搜索应该使用"按引用调用"而不是"按引用传递"这个术语。例如,维基百科将 "Pass-by-reference" 重定向到 "Evaluation Strategy",其中列出了 call-by-reference

在Google图书中使用“按引用方式调用”作为搜索词,可以找到来自《计算机杂志》1963年8月6:134-143(英国计算机学会)的“CPL的主要特点”的片段。
三种参数调用模式是可能的;按值调用(等同于ALGOL按值调用),按替换调用(等同于ALGOL按名称调用)和按引用调用。在后一种情况下,实际参数的LH值被传递;这对应于Strachey和Wilkes(1961年)建议的“按简单名称调用”。请注意与三种初始化方式的对应关系...
后者的“按名称调用”可能是Algol 60规范中使用的相同术语,正如Stephen C在本主题中指出的那样。
(我认为“ Strachey and Wilkes”来自CACM 1961,但我没有任何可验证的来源文本。)

好的,你提供的“Strachey & Wilkes”在ACM Portal引用页面上显示是来自CACM vol 4 issue 11(1961年11月)。 - John R. Strohm

2

我认为这个概念可以追溯到PASCAL,甚至更早。

最初的FORTRAN通过引用传递参数:即传递变量、数组或矩阵的地址。

ALGOL-60通过名称或值传递参数。按名称调用后来被证明是一个巨大的错误,它教会了编程语言设计者很多关于什么不应该做的事情。PASCAL根据参数是否标记VAR(按引用传递)来决定是按值还是按引用传递参数。


很棒的回答!所以我猜Fortran是在57年出现的,Pascal是在70年代初出现的?他们使用“引用(reference)”这个术语还是只有概念呢? - Paul Biggar
@Paul - 他们使用了不同的术语;请看我的回答。 - Stephen C
作为一条注释,Pascal修订报告(http://www.fh-jena.de/~kleine/history/languages/Wirth-PascalRevisedReport.pdf)没有提到“按引用传递”,而是使用“变量引用”(第9.1.2节)。 - Andrew Dalke

2
最早使用“引用”一词,如“按引用传递”,可能已经失传了。无疑,FORTRAN通过引用传递其参数,并且始终如此。
提到“按名称调用”让我想起了尼古拉斯·沃思(Pascal的发明者)的一个笑话(可能是唯一的一个):
“教授,您的姓怎么发音?”
“如果按名称调用,它是V-I-R-T,但如果按值调用,则是W-O-R-T-H。”
人们说程序员没有幽默感!

1

我想你可以追溯到 C,它有指针、引用和解引用运算符。


2
我从未听说过“引用”这个术语与C有关。 - Paul Biggar
1
1975年的C 参考手册(请见http://cm.bell-labs.com/cm/cs/who/dmr/cman.pdf)在多个地方使用了“reference”一词:“由于在任何上下文中(特别是作为实际参数),对数组的引用被视为指向数组第一个元素的指针”,“对同一外部标识符的引用是对同一对象的引用”,至少还有一个地方。我手头没有可搜索的K&R或ANSI C副本。 - Andrew Dalke
好的,虽然我似乎无法撤回我的反对票。抱歉 :( - Paul Biggar

1

我一直以为的想法是区分指针和引用。 引用会指向对象所在的位置。

指针是指向内存中的地址,但在托管语言中,这可能会改变。 因此,您必须通过引用进行抽象,以确保您的代码始终正常工作。 例如,在托管语言中使用数组时,您不能只写reference ++,因为垃圾回收器可能会移动您的数组。 请注意,我非常了解C#中固定和不安全的代码:)。

正如我的Java导师所解释的那样,引用的另一个关键“概念”是您无法操作它。 指针用于程序员管理,引用用于编译器/运行时管理。


1

“引用”这个术语的使用一直不太一致。

  • 在某些情况下,它是一个有形的实体,例如Simula/Delphi/Java/C#对象引用。您可以将它们进行比较(包括null和彼此之间),并将它们作为参数传递(按值或按引用)。
  • 大多数语言都支持引用作为参数传递的一种方式,以完全不透明的方式。
  • C++是唯一一个我知道的扩展了这个不透明模型并允许您拥有引用字段和变量(int& r = i;)的语言。

其中一件事是,这意味着C++引用与C#引用非常不同。

我认为我们在这里缺少一些行话来区分这两种不同形式的“引用”。

另请参见SO: History of public/private/protected


从我的记忆中,Simula是在60年代末(67年?)出现的,因此它似乎是“引用”一词被用于表示托管对象的“新用途”中的第一个。这是否准确(我不知道它有多“托管”)? - Paul Biggar
保罗,请查看链接。Simula(1967)开创了“引用类型”的道路。但在类型安全的意义上尚未“受控”。 - H H

0
请注意,在60年代(是的,一直到70年代),“引用”意味着使用某个东西的名称。这与旧哲学和语言学术语“指称”和“参照”使用方式相符。来自Fortran 77

2.12 引用

变量、数组元素或子字符串引用是在语句中出现变量、数组元素或子字符串名称,分别在上下文中需要使用该实体的值来执行可执行程序时。当执行对实体的引用时,其当前值可用。在此标准中,定义实体的行为不被视为对该实体的引用。

过程引用是在语句中出现过程名称,在上下文中需要执行过程指定的操作以在可执行程序执行期间执行。当执行过程引用时,必须可用该过程。


这似乎是在讨论“解引用”的意义,而不是“按引用调用”。该术语还有其他用法吗? - Paul Biggar
在引用被称作引用之前,当“按引用调用”被称为“按名称关联”时(正如Stephen C所指出的),“引用”具有不同的用途。在60年代到现在之间,“引用”的含义发生了变化。 - outis
以上和史蒂芬的回答(尤其是第三点)提出了一个可能的词源: “按名称关联”是“按名称调用”的更严格版本,只允许将变量引用(指“命名某物的东西”)与虚拟参数相关联。这是否有任何真实性取决于当时这两种调用语义之间的差异有多明确,以及是否有人在乎使这两种语义更加不同。 - outis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接