引用 (程序设计)

电脑科学中,参照(英语:reference)是指一个可以让程式间接存取于电脑记忆体或其他储存装置中一特定资料的,该数据可以为变数记录

参照和资料本身不同。一般而言,参照会是资料储存于记忆体或储存装置中的实体位址。因此,参照亦常被称为该资料的指标位址。不过,参照也被用来指资料位址和某一固定“基准”位址的偏移值,或是阵列的索引。

参照的概念和其他如关联键识别字之类用来识别特定资料项目的值不同,后者只能透过资料库表中的寻找运算,来存取资料。

参照被广泛用于程式设计之中,尤其是用于将大量或易变的资料有效地透过参数传给子程式,或在不同的用途中共享此类资料。此外,参照也能指向一个包含其他资料之参照的变数或记录,此一概念为间接定址连结资料结构(如连结串列)之基础。

例子

指标是最简单的参照,由于和底层硬体的亲密关系,使其成为最强大及有效的参照之一。不过,也因为此一关系,程式设计师在使用指标时,必须非常了解记忆体架构的细节。因为指标储存记忆体的位址,而非直接储存值,不正常地使用指标会导致程式出现未定义行为智慧指标是一个非透明指标,作用和指标相似,但只能透过特定方式存取。

控制代码是一种抽象参照,可用许多不同方法呈现。其中一个常见的例子为档案控制代码(用于C语言标准输入/输出函式库中的档案资料结构 ),用来描述抽象的档案内容。档案控制代码通常可用来表示档案本身(当要求该档案的时),以及档案内容中的某一特定位置(当读存该档案时)。

分布式计算中,参照可能包含一个以上的位址或识别字;也可能包括用来定位或存取参照物件之网路协定的编码格式,用来说明讯息被编码或序列化之方式。举例来说,WSDL中对远端网路服务的描述可被视为一种参照,包括如何定位及绑定特定Web服务之完整格式。另一个例子为对即使分布式物件的参照:该参照为一个如何建设称之为“代理(proxy)”之小型软体元件的完整格式,此代理接著会执行点对点(peer-to-peer)的互动,并使本地机器得以存取被复装或只存在部分一致之讯息串流的资料。

程式语言的支援性

在第一个被使用的程式语言-组合语言中,一般使用未处理的记忆体位址或阵列中的索引表示参照。这样使用是可行的,但有点微妙,因为一个位址无法告诉你它指向的值是什么,更不用说这个值有多大,或是该如何解释;此类讯息都内含在程式的逻辑之中。如此一来,误解将可能出现在不正确的程式里,引发令人感到困惑的错误。

最早的不透明参照为LISPCONS函式,此一函式只是一个包含两个参照至其他Lisp物件的记录,其他Lisp物件也可能包括其他的cons函式。此一简单的结构最常被用来建构单向连结串列,但也可用来建构简单的二元树,以及一种被称为“点状串列”的结构,该结构最终会终止于一个值上,而非空参照。

另一个早期的语言-Fortran则没有明确用来表示参照的用法,但可以传参照呼叫的方式使用参照。

指标依然是今日最常见的一种参照,类似于组合语言中对未处理记忆体位址的表示方式,不同之处在于指标带有一个固定之资料型别,可在编译期间用来确保所指之资料不被误解。不过,因为C语言有个可以使用型别转换(在不同指标型别间及指标型别与整数间转换)的弱型别系统,虽然较为困难,但还是有可能误解。C++试图在C++标准程式库中使用新的cast运算子及较聪明的指标,以增加型别安全;但为了相容性,仍保留绕过这些安全机制的能力。

许多今日常见的主流语言,如EiffelJavaC#Visual Basic等,则均采用了一种更加不透明的参照,通常即简称为“参照”。此类参照具有类似C语言指标的型别,会指出其所参照资料的意思;不过,此类参照为型别安全的,无法指向一个未处理的位址,以及进行不被允许的不安全转换。

参照与指标的区别

对于同时支持参照与指标的C/C++,两类数据型的区别有:

  • 指针可以重新赋值,而参照在初始化绑定后就不能再绑定到其他对象。
  • 指针对象有它自己的内存地址与内存长度,而参照与它指向的对象具有相同的内存地址、内存长度。因此,可以把参照看作是被指向对象的另一个名字。
  • 指针可以指向另一指针,因此允许多层的指针间址(indirection);而参照只允许到对象的一层间址,不允许“参照的参照”。
  • 指针可以直接赋值为NULL,参照不能。当然,可以费劲办法把参照绑定到内存的NULL上,但这并不实用。
  • 指针可以在数组上遍历(iterate),参照不能。
  • 指针需要用运算符“*”来解参照(dereference)以访问它所指向的内存的内容;参照不需要显式解引用。指向类/结构的指针访问成员变量/成员函数需要用运算符->而参照使用运算符.来访问成员。
  • 指针是一个变量,保存了内存地址;而C++标准都没有明说参照是如何实现的。实际上,几乎所有C++编译器把参照作为一个隐式的指针来实现。
  • 指针可以成为数组的成员类型,即指针数组;但参照不可以作为数组的成员类型,即不存在“引用数组”。
  • const参照可以绑定到临时对象;而指针不能(例如,int *y = 12;编译出错)。按照C++11语法,const左值引用可以绑定到一切对象,包括const左值对象,非const左值对象,const临时对象,非const临时对象;右值参照当然可以绑定到临时对象。

参考文献

参见