我有以下代码:
$headers;
some_sub( %$headers );
当我致电some_sub
时,我收到错误消息:
不能在...
中使用未定义的值作为HASH参考
但类似的代码不会产生错误:
$headers->{ x };
为什么自动更新在第一个示例中的工作方式与在第二个示例中的工作原理相同?
UPD
我注意到 @ThisSuitIsBlackNot 。我真的问:
为什么我的$ h; $ h-> {foo}的作品和我的$ h; %$ h不是
UPD
真正的代码:
my $email = Email::Simple->create(()
,header => [()
,To => $address
,From => $cnf->{ from }
,Subject => $subject
,'Content-Type' => 'text/html; charset="utf8"'
,%$headers
]
,body => $body
);
答案 0 :(得分:5)
%$hash
绝对会自动生成。
$ perl -Mstrict -wE'my $foo; say $foo // "undef"'
undef
$ perl -Mstrict -wE'sub f { } my $bar; f(%$bar); say $bar // "undef"'
HASH(0x10b50e0)
错误消息来自some_sub
中的其他内容,可能是来自@_
的错误分配。
答案 1 :(得分:5)
注意问题中添加的代码说明了为什么不进行自动更新。
短你的sub采用一个列表(hash),它有一个匿名数组作为元素 - %$headers
被隐藏在那个数组中。它是 anon数组
这是标量别名,因此不需要%$headers
可修改。因此,不会发生自动更新,并且您将获得下面描述的致命运行时错误,因为尝试对未定义的引用进行解除引用。
%$ref
在左值上下文中使用时自动生成。这可能发生在子呼叫中,见下文。
您显示的错误是由于使用了未定义的引用。例如,声明
my %hash = %{ $ref };
尝试从$ref
中存储的内存位置复制哈希值并将其分配给%hash
。符号%hash
是在编译时创建的,但如果在$ref
没有找到哈希,或者$ref
中没有任何内容,则会出现错误。这里没有自动生成。 use strict
生效
perl -wE'use strict; my $h; my %h = %$h; say $h'
这会抛出致命的运行时错误
Can't use an undefined value as a HASH reference at -e line 1.
当eval
- 生存时
perl -wE'use strict; my $h; my %h = eval { %$h }; say $h; say "hi"'
它会打印一条关于“未初始化的值”的警告,一个空行,然后是hi
。没有哈希。
但是,当在子程序调用中用作参数时,它会自动生成
perl -wE'use strict; sub tt { 1 }; my $h; tt( %$h ); say $h'
因为这会打印行HASH(0x257cd48)
,而不会出现警告或错误。
在左值上下文中使用解除引用的对象时会发生自动生成,这意味着它需要可修改。在子例程调用中,原因是函数的参数在@_
中有别名,因此必须可以修改它们。相同的别名需要使它在foreach
循环中发生,而keys
重置散列迭代器。请参阅this post和this post以及this post。
感谢ThisSuitIsBlackNot的解释和链接。
在您的情况下,%$ref
作为匿名数组的元素传递,因此没有别名(arrayref本身是)。所以autvivication没有启动,你得到了这个错误。
在Perl中,存储位置(左值)会根据需要自发生成自己,包括创建任何硬参考值以指向下一级存储。赋值
$a[5][5][5][5][5] = "quintet"
可能会创建五个标量存储位置,以及四个引用(在前四个标量位置中)指向四个新的匿名数组(用于保存最后四个标量位置)。但自动更新的关键是你不必担心它。