本文介绍了为什么$ foo-> {bar}会自动恢复,而%$ foo不能恢复?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

$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不能恢复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 17:27