对现代计算机语言中值和引用的思考
首先需要将 变量 和 数据 区分开。变量是语言层面的概念,数据是存储层面的概念。变量和值之间是所有制关系。变量拥有不同类型的值。
数据分为 基本数据类型 和 复合数据类型。复合数据类型包含 引用。引用会在稍后介绍。
值为基本数据类型的变量相互赋值时,会直接进行拷贝。
值为复合数据类型的变量给对方赋值时,由于不确定拷贝的成本,采用默认懒惰的策略,只传递对方的 引用。这里引用是一个抽象概念,和物理地址类似。变量自己不拥有数据,只拥有数据的引用。每当进程访问变量时,会根据引用找到数据。关键在于这一份数据不是变量私有的,可以被多个变量通过一个引用共享。
1 | a = [1,2] |
在抽象层面上,a 可视为一个列表。但在物理层面上,a 是一个单一的值,即为引用。这种二元性是很多困惑的根源。
1 | a = [[1,2],[3,4]] |
a 的值是一个引用。这个引用指向两个引用组成的列表,两个引用分别指向 [1,2]
和 [3,4]
1 | b = a |
如此赋值时,b 的值也是一个引用,同样指向两个引用组成的列表。
1 | b.append([5]) |
b 的值是一个指向列表的引用,b.append
会向该引用指向的列表添加一个元素 [5]