将预编译的正则表达式放在列表中引用的两个不同哈希中:
my @list = (); my $regex = qr/ABC/; push @list, { 'one' => $regex }; push @list, { 'two' => $regex }; use Data::Dumper; print Dumper(\@list);
我期待:
$VAR1 = [ { 'one' => qr/(?-xism:ABC)/ }, { 'two' => qr/(?-xism:ABC)/ } ];
但相反,我们得到一个循环引用:
$VAR1 = [ { 'one' => qr/(?-xism:ABC)/ }, { 'two' => $VAR1->[0]{'one'} } ];
这将发生在无限期嵌套的哈希引用和浅层复制$regex
.
我假设基本原因是预编译的正则表达式实际上是引用,并且同一列表结构中的引用被压缩为优化(\ $标量行为相同).我没有完全看到这样做的效用(可能是对引用的引用具有相同的内存占用),但也许基于内部表示的原因
这是正确的行为吗?我可以阻止它发生吗?除了可能使GC更加困难之外,这些圆形结构会产生非常严重的问题.例如,迭代有时可能包含相同正则表达式的查询列表会使MongoDB驱动程序崩溃并发生令人讨厌的段错误(请参阅https://rt.cpan.org/Public/Bug/Display.html?id=58500)
这是预期的行为.
你的参考不是真正的循环; 你有两个单独的项目,指向同一件事.数据::自卸车正在打印您的数据结构的人类可读,Perl的可分析表示在内存中,它真正的意思是,无论$list[0]->{one}
和$list[1]->{two}
指向同样的事情.
Perl使用引用计数垃圾收集,虽然它可能会遇到循环数据结构的问题,但这种数据结构没有特别的问题.
这里没什么好笑的.
您在同一数据结构中存储了两次相同的引用.
然后你要求Data :: Dumper打印该结构的表示.
数据::自卸车要往返你给它尽可能忠实地将数据,这意味着它需要输出的Perl代码,将生成一个包含在相同的数据结构$list[0]{one}
,因为它确实在$list[0]{two}
.
它通过输出数据结构来实现这一点,其中一个成员包含对同一结构的另一个成员的引用.
但它实际上并不是一个循环引用.