基本上你可以预期一个纯量变量会对应到内存中的固定一小片空间,其位置几
乎 [^1] 不会变。但若是用 print 去印的某个内容物是参照的变量的话,
印出来的后面那个数字代表的不是变量本身的位置,而是其内容物的位置。
以下面这个例子而言,印 "$Ref" 会显示出 $AAA 的位置。
my $AAA = 0;
$Ref = \$AAA;
print "1:$Ref\n";
如果你想要得知 $Ref 的位置,可以透过 Devel::Peek 模组的 Dump() 函式:
my $AAA = 0;
$Ref = \$AAA;
Dump($Ref);
然后会在 STDERR 上看到这一大片表示纯量变量内部结构的文字:
SV = IV(0xe33cf4) at 0xe33cf8
REFCNT = 1
FLAGS = (ROK)
RV = 0xe33cd8
SV = IV(0xe33cd4) at 0xe33cd8
REFCNT = 2
FLAGS = (IOK,pIOK)
IV = 0
其中 16 进位数字就是位置,而前面 SV / IV 这两个关键字对应到的是
perl5.git 原始码中的资料结构。SV 对应到纯量变量 (scalar variable),IV
对应到整数数值 (integer value)。还有很多其他种类,很有兴趣的的话可以略
看一下 perlguts 这份文件:
https://perldoc.perl.org/perlguts
其中第一行 SV 后面的 at 0xe33cf48 就是 $Ref 的位置,
而第五行的 SV = ... at 0xe33cd8 则是 $AAA 的位置。
回到你的原问题:
为什么我使用my宣告后的第二次重新指定变量内容会让Perl指向新的内存位置,
而没有宣告的部份却是指向一样的位置?
我认为这是为了让实做上方便而必然的结果,如果从 `my` 的文件这段来看:
https://perldoc.perl.org/functions/my (或: perldoc -f my)
Redeclaring a variable in the same scope or statement will
"shadow" the previous declaration, creating a new instance and
preventing access to the previous one.
既然同名变量第 n+1 次的宣告必须将第 n 次的宣告内容盖掉,那要不就是用沿用同一个容器,
把旧的值清理干净,相关副作用全部正确发动完毕之后再后装新的值进来,要不就是准备一个新容器,
让后旧的放在原地让 GC 机制 (ref count) 去清理。
考虑到参照物可能是所有资料型别,第二种准备新容器的做法应该比较省事。
简单讲就是:在同一段语意范围内宣告了两个 $AAA 的话,相当于是两个不同变量。
只是第二个出现后第一个就变成找不到了。
[^1]: 我一时之间还真想不到有没有什么状况会变。我猜如果 fork() 后再修改内容,
让 copy-on-write 发生,应该就会变。