关于this问题,手动设置之间的区别是什么
到undef
列表元素和Perl在增加大小时设置的元素
当列表时,通过分配比列表大小更大的索引来列出该列表
走样?例如,考虑以下代码:
@a = (undef, 0);
@b = ();
$b[1] = 0;
print Dumper(@a), "\n", Dumper(@b);
它打印(按照预期,我认为):
$VAR1 = undef;
$VAR2 = 0;
$VAR1 = undef;
$VAR2 = 0;
那么,数组不一样吗?显然不是:
sub change { $_[0] = 1 }
change(@a); change(@b);
print Dumper(@a), "\n", Dumper(@b);
打印哪些:
$VAR1 = 1;
$VAR2 = 0;
$VAR1 = undef;
$VAR2 = 0;
答案 0 :(得分:17)
你找到了一个引人入胜的边缘案例。
当您明确设置元素时,它首先会存在。如果扩展数组以使多个索引落入此数组的范围内,则不会在这些位置隐式初始化标量。例如:
my @array;
$array[2] = undef; # this extends the array
# now elements 0–2 report as `undef`, but only #2 was initalized
当我们询问这些元素是否存在时,我们得到:
say "index $_ ", exists $array[$_] ? "exists" : "doesn't exist" for 0 .. 4;
输出:
index 0 doesn't exist
index 1 doesn't exist
index 2 exists
index 3 doesn't exist
index 4 doesn't exist
此优化可以避免在这些位置分配未使用的标量;当没有任何说明的情况下,数组访问代码只返回undef
。
现在这与函数调用非常相似。调用子例程时,会在堆栈上放置一个平面的标量列表,然后可以将其作为@_
访问。这里没有复制,所以这是别名调用。现在,当您在子资源中访问$_[0]
元素时,此处没有标量,因此它会在@_
中创建一个新标量:
sub crazy {
say 1*exists $_[0];
$_[0] = 1;
say 1*exists $_[0];
}
my @array; $array[2] = 0;
crazy @array;
say 1*exists $array[0];
输出:
0
1
0
在内部,标量是指向SV
结构的指针。这些指针被复制到堆栈中,因此这使得原始@array
的实际修改成为不可能。
答案 1 :(得分:6)
一个区别是exists $a[0]
为真,exists $b[0]
为假。