值在哪里、名字指向什么:内存与引用
程序运转的时候,我们做出的值, 总得装在某个地方。 那个地方,就是内存。 想象一面排满了编号储物格的墙。 名字,就是指向其中某一格的便条。
值,总装在某个地方
程序运转的整段时间里,
每个值都会在内存某处占下一个位置。
内存就像一面排满编号储物格的墙。
做一个值,它就溜进一个空格。
程序,是用「第几号格」来记住值的。
点「放入值」。它进一个空格,格号也显出来。
每个值都有了自己的格和号了吧。
可我们在代码里,不写「第7格」对吧?
我们写「a」「分数」这样的名字。
那名字,和格号,是怎么连上的呢?
名字,指向那个位置
名字,不是值本身。
是一张知道「哪一格」的便条。
名字「a」→ 第3格 → 里面的 7。
所以你用「a」,程序就顺着便条,
打开第3格,读出 7。这就是「指向」。
点名字「a」。顺着便条到那格,把里面的值取出来。
名字指向格,那格里装着值。
这张「指向的便条」,叫做引用。
好,从这儿起,才是真正要紧的。
要是说「把 a 也给 b」,会发生什么呢?
小值,会被复制
把数字这样的小值给 b,
那个值就原样复制到一个新格里。
现在 a 是第3格,b 是第5格。是不同的格。
所以就算把 a 改成 9,b 还是 7。
两者各自拿着自己的值,是独立的。
先点「复制到 b」,再点「改 a」。b 是另一格,所以不变。
复制的小值,彼此不影响。很干净。
可像对象这样大的东西,情形就不一样了。
把大东西整个复制,是很重的。
所以常常,不是复制,而是发生别的事。
大的东西,共指一个格
把对象给 b 时,并不复制整个对象,
常常让 b 也指向同一个格。
现在 a 和 b,两张便条,一起指着同一格。
所以你用 a 改那个对象,
用 b 看,也一样变了。因为是一个东西,两个名字。
两个名字指着一个格,改一个,两个都变。
初学编程时,最常被吓到的,就是这一处。
「我根本没碰 b,它怎么变了?」
现在你知道答案了:它们一直指着同一个格。
弄清指向什么,就不再糊涂
糊涂的真身,永远是一个。
名字是拿着自己的复制,还是共指着一个东西。
小值就是复制,各走各的,
大东西就共指一格,一起动。
只要想起这个区分,就不会再吃惊了。
选「小值」和「大东西」,做同样的事。结果怎么分,看得见。
到这儿,就是编程的根基了。
从一个值开始,打包、重复、起名,
聚成对象,靠调试修好,让机器去跑。
如今,又看到了这一切装在哪儿,
名字指向什么。一个扎实的根基,建起来了。