gpt4 book ai didi

Perl 5 : assignment of an anonymous arrayref, 数组仍然为空 = 复制构造?

转载 作者:行者123 更新时间:2023-12-02 18:06:37 27 4
gpt4 key购买 nike

我认为我对 Perl 引用以及如何使用它们有所了解。我开始接触 Perl 5.005。现在我有一段用 Perl 5.32 新鲜编写的代码,其中一些数组引用操作的行为让我感到困惑。

这是我的最小示例:

#!/usr/bin/perl

my $array_ref = (); # create an anonymous array and keep a reference to it
my $another_ref = $array_ref; # assign the reference (not an array deep copy, or is it?)

print "Pushing foo and bar\n";
push @{ $array_ref }, "foo";
push @{ $array_ref }, "bar";

print "Array ref element count: " . $#{ $array_ref } . "\n";
print "Another ref element count: " . $#{ $another_ref } . "\n";

print "Pushing baz\n";
push @{ $array_ref }, "baz";

print "Array ref element count: " . $#{ $array_ref } . "\n";
print "Another ref element count: " . $#{ $another_ref } . "\n";

结果输出:

# ./test.pl
Pushing foo and bar
Array ref element count: 1
Another ref element count: -1
Pushing baz
Array ref element count: 2
Another ref element count: -1

我的生产代码创建一个空的匿名数组 = 获取对其的引用,然后将引用的副本存储在某些动态数据结构中,然后继续使用原始的“my”( local)引用,然后“我的”本地标签超出范围。对我来说奇怪的是,虽然元素确实被添加到最初获得的数组引用中,但它们不会通过“复制的引用”= 出现,就像行一样

my $another_ref = $array_ref;

行为更像是复制构造,我最终得到了一个新的独立数组。即,根据观察到的行为,它似乎执行了深度复制。Perl 没有报告任何语法错误。

然后我想到,在将一些元素推送到原始数组之后尝试 arrayref 赋值。源代码中移动了一行:

#!/usr/bin/perl

my $array_ref = (); # create an anonymous array and keep a reference to it
#my $another_ref = $array_ref; # moved below:

print "Pushing foo and bar\n";
push @{ $array_ref }, "foo";
push @{ $array_ref }, "bar";
my $another_ref = $array_ref; # moved here

print "Array ref element count: " . $#{ $array_ref } . "\n";
print "Another ref element count: " . $#{ $another_ref } . "\n";

print "Pushing baz\n";
push @{ $array_ref }, "baz";

print "Array ref element count: " . $#{ $array_ref } . "\n";
print "Another ref element count: " . $#{ $another_ref } . "\n";

结果输出:

# ./test.pl
Pushing foo and bar
Array ref element count: 1
Another ref element count: 1
Pushing baz
Array ref element count: 2
Another ref element count: 2

现在看起来确实像一个正确的“仅引用的副本”。

所以我得到了对空数组的引用的深拷贝,但得到了填充数组的浅拷贝?哎哟!这是一个功能吗?通过什么方式?

这让我想知道我是否介意。我确实可以选择在“初始”范围的末尾分配数组,其中匿名数组被实例化。如果到该范围结束时数组仍然为空,则稍后确实可以添加更多元素,但到那时原始引用将消失,并且无论如何我都只能通过“持久”引用访问数组=一致的结果 = 没有造成任何伤害,只是在我的特殊情况下需要注意一些事情。

最佳答案

声明 $array_ref 的第一行不会“创建匿名数组

my $var = ();  # just an uninitialized scalar

仅声明一个标量变量,并为其分配一个空列表,根本没有任何效果。 该变量保持未初始化状态。人们可以通过打印它的 ref 来看到这一点。 ,它显示一个空字符串(不是 ARRAY),或者尝试打印它,您会收到使用未初始化值的警告(不是 ARRAY(0x...)),数组引用的字符串化)。或者使用Devel::Peek

因此,在再次声明该变量时将该变量分配给另一个变量没有任何效果,并且 $another_ref 只是另一个未初始化的、完全不相关的标量。

但是声明了一个标量,并且没有初始化它,仍然允许我们将其转换为引用。因此,当您取消引用它,将值插入其中时,确实会构造一个匿名数组(通过自动生存),然后

push @$var, 1;  # now it "became" an array reference

$var 是一个数组引用。好吧,它是一个标量,其值是一个数组引用,所以没有什么非常奇怪的事情发生,这就是通常的做法:声明一个标量,然后为其分配/构造一个引用。然而,这可能会令人惊讶。

在第二次尝试中,$another_ref确实被分配了一个数组引用,因为同时$array_ref确实被“提升”为数组引用。 (但这不是“深层复制”,并且仅对于对没有元素引用的数组的引用有效。)

声明一个标量将其放入数组引用中

my $array_ref = [];

这通常是不需要的,因为一旦以这种方式使用,用于数组引用的未初始化标量就会变成一个标量。

一个异常(exception)是,如果该标量需要传递到一个子例程中,该子例程需要能够判断它是否获得了引用;那么我们需要首先为其分配一个引用。


如果已定义变量,则会对其产生影响。对于数组,@ary = (); 清除所有值(但保留内存分配,与 undef @ary; 不同);对于标量,它分配一个 undef

不过,也许很奇怪的是,我们可能会将一个未定义的标量视为数组引用(通过取消引用它并将值推送到它上面),并且它确实变成了一个数组引用

关于Perl 5 : assignment of an anonymous arrayref, 数组仍然为空 = 复制构造?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73106099/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com