我在第9行的代码中创建了哈希的本地副本。对%d的任何更改都不会对全局%h变量(行:5)进行更改。我必须使用reference(第8行)来提供对%h的更改。
有没有办法在不创建本地副本的情况下取消引用子哈希? 我问,因为我有许多参考文献的复杂记录,并且通过引用来导航它会更容易。
1 #!/usr/bin/perl -w
2 use strict;
3 use warnings;
4
5 my %h;
6 sub a {
7
8 my $href = shift;
9 my(%d) = %{$href}; # this will make a copy of global %h
10
11 $$href{1}=2; # this will make a change in global %h
12 $d{2}=2; # this will not a change in global %h
13 }
14 a(\%h);
15 print scalar (keys %h) . "\n";
感谢您的回复。
问题是我可以在sub中对%h进行某种“别名/绑定”。 我想在%d中改变%h中的%h的上下文。 每当我创建%d时,他都会制作%h的本地副本 - 是否有任何方法可以避免这种情况,或者我是否必须始终使用引用?
再一次:)我知道$ href是如何工作的。我阅读了教程/手册/文档等。 我没有在那里找到答案 - 我认为这是不可能的,因为它没有写在那里,但谁知道。
我想完成这样的行为:
6 sub a {
7 $h{"1"}=2;
8 }
这相当于:
6 sub a {
8 my $href = shift;
11 $$href{1}=2; # this will make a change in global %h
11 $href->{1}=2; # this will make a change in global %h
现在如何在%d的帮助下做到这一点 - 实际上可能吗?
6 sub a {
7 my %d = XXXXXXXXX
.. }
在不创建本地副本的情况下,我应该在XXXXXXXXX下指向%h?
答案 0 :(得分:6)
要创建值的本地别名,您需要使用Perl的包变量,可以使用typeglob语法对其进行别名(并使用local
来区分别名):
#!/usr/bin/perl -w
use strict;
use warnings;
my %h;
sub a {
my $href = shift;
our %alias; # create the package variable (for strict)
local *alias = $href;
# here we tell perl to install the hashref into the typeglob 'alias'
# perl will automatically put the hashref into the HASH slot of
# the glob which makes %alias refer to the passed in hash.
# local is used to limit the change to the current dynamic scope.
# effectively it is doing: *{alias}{HASH} = $href
$$href{1}=2; # this will make a change in global %h
$alias{2}=2; # this will also make a change in global %h
}
a(\%h);
print scalar (keys %h) . "\n"; # prints 2
这是一种相当先进的技术,因此请务必阅读local
和typeglobs
上的Perl文档,以便准确了解正在发生的事情(尤其是{{1}内调用的任何潜在客户1 {}} a
之后的子例程也会在范围内local
,因为%alias
表示动态范围。本地化将在local
返回时结束。)
如果您可以从a
安装Data::Alias
或其他一个别名模块,则可以避免使用包变量并创建词法别名。上面的方法是没有额外模块的唯一方法。
答案 1 :(得分:2)
使用哈希引用的两种方法:
你自己使用的是
$$href{'key2'} = "key2";
上面指出:
$href->{'key1'} = "key1";
答案 2 :(得分:1)
这对您有帮助吗
$href->{1} = 2;
print scalars (keys %{$href});
答案 3 :(得分:0)
以下代码显示了如何使用箭头运算符取消引用(是的,不创建局部变量)
阅读this以获取有关解除引用的教程以及可能的不同类型的解除引用。
use warnings;
use Data::Dumper::Simple;
my %h;
sub a {
my $href = shift;
#dereference using the arrow operator - *preferred*
$href->{name} = "John";
}
a(\%h); #Passing the reference of the hash
print Dumper(%h);
为什么你需要首先将作为全局的哈希值作为参数传递给子例程?