问题描述
我有以下代码:
$headers;
some_sub( %$headers );
致电some_sub
时出现错误:
但是类似的代码不会产生错误:
But similar code does not produce an error:
$headers->{ x };
为什么第一个示例中的自动生存功能与第二个示例中的自动生存功能不同?
Why doesn't autovivification work the same way in the first example as it does in the second?
UPD
我由 @ThisSuitIsBlackNot 记录.我真的要问:
I noted by @ThisSuitIsBlackNot. I really ask:
UPD
真实代码:
UPD
The real code:
my $email = Email::Simple->create(()
,header => [()
,To => $address
,From => $cnf->{ from }
,Subject => $subject
,'Content-Type' => 'text/html; charset="utf8"'
,%$headers
]
,body => $body
);
推荐答案
注意问题中添加的代码说明了为什么不进行自动生存.
Note Code added to the question demostrates why autovivification doesn't happen.
短您的子项使用一个列表(哈希),该列表具有一个匿名数组作为元素–.并且%$headers
埋在该数组中.这是 anon数组它是标量的别名,因此不需要%$headers
可修改.这样就不会发生自动生存,并且由于在未定义的引用上尝试取消引用,您会遇到以下致命的运行时错误.
Short Your sub takes a list (hash) which has an anonymous array as an element – and %$headers
is buried in that array. It is the anon arraythat is the scalar aliased to, thus there is no requirement for %$headers
to be modifiable. Thus no autovivification happens, and you get the fatal runtime error described below, as dereferencing is attempted on an undefined reference.
%$ref
在左值上下文中使用时会自动保留.这可能会在子调用中发生,请参见下文.
A %$ref
autovivifies when used in lvalue context. This may happen in a sub call, see below.
您显示的错误是由于使用了未定义的引用.例如,语句
The error you show is due to the use of an undefined reference. For example, the statement
my %hash = %{ $ref };
尝试从存储在$ref
中的内存位置复制哈希并将其分配给%hash
.符号%hash
是在编译时创建的,但是如果在$ref
上未找到哈希,或者在$ref
中没有任何内容,则会出现错误.这里没有自动生存.启用use strict
attempts to copy a hash from the memory location stored in $ref
and assign it to %hash
. The symbol %hash
is created at compile time, but if no hash is found at $ref
or if there is nothing in $ref
, we get an error. No autovivification happens here. With use strict
in effect
perl -wE'use strict; my $h; my %h = %$h; say $h'
这会引发致命的运行时错误
this throws the fatal runtime error
Can't use an undefined value as a HASH reference at -e line 1.
当eval
-ed要生存下来
perl -wE'use strict; my $h; my %h = eval { %$h }; say $h; say "hi"'
它将显示有关"未初始化的值",空行和hi
的警告.没有哈希值.
it prints a warning about "uninitialized value", an empty line, and then hi
. No hash.
但是,当在子例程调用中用作参数时,它会自动生存
However, when used as an argument in a subroutine call it autovivifies
perl -wE'use strict; sub tt { 1 }; my $h; tt( %$h ); say $h'
,因为这将打印行HASH(0x257cd48)
,而没有警告或错误.
as this prints the line HASH(0x257cd48)
, without warnings or errors.
当在左值上下文中使用了被取消引用的对象时,会发生自动生存,这意味着它需要可修改.在子例程调用中,其原因是函数的参数在@_
中具有别名,因此必须可以对其进行修改.相同的别名需求使其在foreach
循环中发生,而keys
重置哈希迭代器.参见这篇文章和和.
The autovivification happens when a dereferenced object is used in lvalue context, which means that it needs to be modifiable. In a subroutine call the reason for this is that arguments to a function are aliased in @_
so it must be possible to modify them. The same aliasing need makes it happen in a foreach
loop, while keys
resets the hash iterator. See this post and this post and this post.
感谢 ThisSuitIsBlackNot 以获得解释和链接.
Thanks to ThisSuitIsBlackNot for explanation and links.
在您的情况下,%$ref
作为匿名数组的元素传递,因此没有别名(arrayref本身是).因此,自动生存无法发挥作用,您会收到该错误.
In your case the %$ref
is passed as an element of an anonymous array, and is thus not aliased (the arrayref itself is). So autovivication does not kick in and you get that error.
关于自动生存,来自术语表
例如,还参见 Article 中的文章
Also see, for example, an article from Effective Pearler
这篇关于为什么$ foo-> {bar}会自动恢复,而%$ foo不能恢复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!