Perl:如何将数组引用转换为数组而不创建副本?

5

在C#中,可以创建对引用类型的引用:

SomeObject origObj = new SomeObject();
SomeObject objRef = origObj;

origObj和objRef都指向同一个对象。

现在,在Perl中:

my @arr = (1,2,3);
method(\@arr);

sub method
{
  my $arr_ref = shift;
  foreach my $element (@{$arr_ref})
  {
     #...
  }
}

我希望在方法内部使用 "@myArr" 而不是每次都进行转换:"@{$arr_ref}" - 并且要做到这一点而不创建数组的副本 (因为我的 "@myArr = @{$arr_ref}" 将会创��一个副本)。

总结一下:如何在不创建副本的情况下获取 "@myArr = @{$arr_ref}"?


为什么要费心呢?使用@myArr和使用$arr_ref一样不容易。 - ysth
1
@ysth,就易用性而言,数组索引和数组引用的区别不大,但是数组索引比数组引用稍微快一些(约7%)。 (尽管词法变量比包变量更快,但只有使用Data::Alias解决方案才能获得加速的好处。) - tobyink
2
@Fortmann,@$objs@objs 一样易读。 $objs->[0]$objs[0] 一样易读。阻碍可读性的是所有 _ref 实例和不必要的花括号。 - ikegami
感谢你的建议 - 在我实际的使用情况中,我有一个复杂的哈希$Metric_Config {'Expression'} {'Operations'},它指向了相关的数组。最终我强制转换了@$Metric_Config{'Expression'} {'Operations'},但之后我想要一个简单的指向该数组的指针。你觉得怎么样? - Fortmann
“cast”不是Perl的概念。如果$Metric_Config是哈希引用,你只需要执行$Metric_Config->{'Expression'}{'Operations'}(或者不太流行的样式$$Metric_Config->{'Expression'}{'Operations'})。http://perlmonks.org/?node=References+quick+reference 可能会对你有所帮助。 - ysth
显示剩余2条评论
2个回答

8
如果您希望@myArr成为包变量(our)而不是词法变量(my),您可以这样做:
our @myArr;
local *myArr = $arr_ref;

这将使@myArr表现得像$arr_ref指向的数组的别名。
如果您需要@myArr是词法作用域的,那么可以使用Data::Alias
use Data::Alias;
alias(my @myArr = @$arr_ref);

1
+1,也许可以提到https://dev59.com/oXA65IYBdhLWcg3w1SbU - mpapec
感谢tobyink,看起来完美运行:sub test { our @myArr; local *myArr = shift; print join("\n", @myArr); } - Fortmann
1
你应该知道的一件事是,包变量是全局变量(尽管是有命名空间的)。因此,如果你的 test() 子程序调用另一个子程序,那么另一个子程序也可以访问 @myArr。使用词法变量通常更可取,因为它允许你消除“远程幽灵操作”的来源。出于这个原因,我个人更喜欢 Data::Alias 解决方案而不是包变量。然而,Data::Alias 是一个非核心模块,内部使用了一些非常奇特的技术;在某些 Perl 版本上,它曾经长时间无法使用。 - tobyink
在我的情况下,系统中没有“Data :: Alias”库,我使用上面评论中@ikegami建议的语法解决了我的需求:在@array的位置使用@{$array_ref},在$array [0]的位置使用$array_ref-> [0] - Mariano Paniga

2
Perl 5.22新增了“refaliasing”或赋值给引用的功能,它正是您想要的:
no warnings qw(experimental);
use feature qw(refaliasing);

my $a = [1, 2, 3];

\my @b = $a; # a & b are the same array

my @c;
\@c = $a; # a, b, & c are the same array

push @b, 4;
push @c, 5;

print "@$a\n"; # prints 1 2 3 4 5


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接