问题描述
关于这个问题,手动设置有什么区别到 undef
列表元素和 Perl 在增加大小时设置的元素该列表通过分配比列表大小更大的索引,当别名?例如,考虑以下代码:
Relating to this question, what's the difference between a manually setto undef
list element and one that was set by Perl when growing the size ofthat list by assigning to a bigger index than the list size, when beingaliased? For example, considering this code:
@a = (undef, 0);
@b = ();
$b[1] = 0;
print Dumper(@a), "\n", Dumper(@b);
它打印(我认为是预期的):
It prints (as expected, I think):
$VAR1 = undef;
$VAR2 = 0;
$VAR1 = undef;
$VAR2 = 0;
那么,数组不一样吗?显然不是:
So, aren't the arrays the same? Apparently not:
sub change { $_[0] = 1 }
change(@a); change(@b);
print Dumper(@a), "\n", Dumper(@b);
打印:
$VAR1 = 1;
$VAR2 = 0;
$VAR1 = undef;
$VAR2 = 0;
推荐答案
您发现了一个有趣的边缘案例.
You found a fascinating edge case.
当您明确设置一个元素时,它首先会出现.如果一个数组被扩展使得多个索引落入该数组的范围内,则不会在这些位置隐式初始化标量.示例:
When you explicitly set an element, it first springs into existence. If an array is extended so that multiple indices fall into range of this array, no scalars are implicitly initialized at these positions. Example:
my @array;
$array[2] = undef; # this extends the array
# now elements 0–2 report as `undef`, but only #2 was initalized
当我们询问这些元素是否存在时,我们得到:
When we ask whether these elements exist, we get:
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
.
This optimization saves you from allocating unused scalars at these positions; the array access code just returns an undef
when there isn't anything there stating otherwise.
现在这与函数调用非常吻合.当一个子程序被调用时,一个标量的平面列表被放在堆栈上,然后可以作为 @_
访问.这里没有复制,所以这是别名调用.现在当 $_[0]
元素在你的子中被访问时,这里没有标量,所以它在 @_
中创建一个新的:
Now this squares badly with function calls. When a subroutine is called, a flat list of scalars is put on the stack, which is then accessible as @_
. No copying takes place here, so this is call by alias. Now when the $_[0]
element is accessed in your sub, there is no scalar here, so it creates a new one in @_
:
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
的实际修改变得不可能.
Internally, a scalar is a pointer to an SV
struct. These pointers are copied onto the stack, so this makes actual modification of the original @array
impossible.
这篇关于自动设置为 undef 的数组元素在别名时不会改变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!