为什么 $foo->{bar} 会自动激活而 %$foo 却不会?

2023-12-25

我有以下代码:

$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
);

Note添加到问题中的代码演示了为什么自动生存不会发生。

Short你的 sub 接受一个列表(哈希),其中有一个匿名数组作为元素 - 并且%$headers就埋在那个阵中。它是匿名数组这是别名的标量,因此不需要%$headers可修改。因此,不会发生自动生存,并且您会收到下面描述的致命运行时错误,因为尝试对未定义的引用进行取消引用。


A %$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.
  

When eval-ed 生存下去

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重置哈希迭代器。看这个帖子 https://stackoverflow.com/questions/6419618/perl-vivification-question-while-dereferencing-undefined-array-reference and 这个帖子 https://stackoverflow.com/questions/2206836/why-does-perl-autovivify-in-this-case and 这个帖子 https://stackoverflow.com/questions/35029084/why-does-autovivification-occur-with-keys-and-not/35031218#35031218.

谢谢这套衣服是黑色的不是 https://stackoverflow.com/users/176646/thissuitisblacknot以获得解释和链接。

在你的情况下%$ref作为匿名数组的元素传递,因此没有别名(arrayref 本身是)。所以自动激活不会启动,你会得到这个错误。


On 自动活化 from 术语表 http://perldoc.perl.org/perlglossary.html#A

在 Perl 中,存储位置(左值)根据需要自动生成,包括创建任何硬引用值以指向下一级存储。分配$a[5][5][5][5][5] = "quintet"可能会创建五个标量存储位置,加上四个引用(在前四个标量位置),指向四个新的匿名数组(以保存最后四个标量位置)。但自动生存的要点是你不必担心它。

另请参阅,例如有效佩勒的文章 https://www.effectiveperlprogramming.com/2011/04/understand-autovivification/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 $foo->{bar} 会自动激活而 %$foo 却不会? 的相关文章

  • 对象指针值作为字典的键

    我想使用对象的引用值作为字典的键 而不是对象值的副本 因此 我本质上想在字典中存储与另一个对象的特定实例关联的对象 并稍后检索该值 这可能吗 是不是完全违背了NSDictionary的理念 我可以看出我可能以错误的方式处理这个问题 因为字典
  • 使用 -T 开关运行时 $ENV{ENV} 不安全

    当我尝试最后一个例子时perlfaq5 如何计算文件中的行数 http perldoc perl org perlfaq5 html How do I count the number of lines in a file 我收到一条错误消
  • 在 Perl 中使用数据引用的正确方法

    我有一组想要处理的数据 为了简化我的代码 最好通过指向原始数据的引用数组来访问我的数据的某些子集 比解释更好的是 我写下了这个例子 它还没有工作 最后 我想更新原始数据 而不必更新所有子集 用 Perl 可以做这样的事情吗 usr bin
  • 无法从日志文件中提取特定信息

    我这里有日志文件我想提取以下信息 想要提取十六进制值 如果该行有第二个括号 0 9 想要提取十进制值 首先转换为十六进制 然后提取 9 gt 0x09 想要提取负值 25 先转换为十六进制然后提取 例如 25 gt FFE7 gt 想要提取
  • C++ 在 std::map 中存储对值的引用

    我是否正确地假设向 std map 添加 删除元素不会影响其他元素 即导致它们在内存中重新定位 因此以下内容是安全的 我查看了各个网站上有关容器的信息 但只发现了迭代器无效的情况 这是我已经知道的 std map
  • 客户端浏览器关闭时服务器端 Perl CGI 脚本中断

    我已经尝试解决一个小问题很长一段时间了 但似乎我无法解决 我编写了一个 HTML 页面 它在提交表单时调用 perl CGI 脚本 该 CGI 在服务器端执行一定数量的任务 我让脚本将这些任务的步骤打印到 HTML 页面上的 iframe
  • 快速 Perl signint 处理程序

    收到 Ctrl C 时处理程序清理的最方便 最清晰的方法是什么 例如 当我的套接字服务器以这种方式被终止时 TCP 套接字永远不会关闭 我想要一个很好的衬里 我可以将其放在程序的顶部来设置 sigint 处理程序 或类似 atexit 的东
  • BASH:将数据从平面文件导入模板

    我有一个平面记录文件 每行有 33 行 我需要将此文件格式化为模板中的规格 模板为 DOS 格式 源文件为 NIX 格式 该模板具有必须遵守的特定缩进和间距 我想到了几个选择 BASH 与经典的 nix 工具 sed awk grep 等
  • Perl 程序如何知道在哪里可以找到包含它使用的 Perl 模块的文件?

    如果我的 Perl 程序使用 Perl 模块 它将如何确定在哪里找到包含模块代码的文件 例如 如果程序包含 use MyModule1 Example 1 use This Here MyModule2 Example 2 它会看起来在哪里
  • 如何彻底删除 Perl 中的包?

    如何在 Perl 中彻底删除一个包 这不仅意味着包变量 还意味着 Perl 更新以处理继承更改和其他事情的任何魔术表 这个简单的测试 use warnings use strict use Test LeakTrace use Symbol
  • 使用 Visual Studio Code 调试 Perl

    我今天刚开始使用 Perl 并安装了活动Perl https en wikipedia org wiki ActivePerl5 24 1 一切都很顺利 我能够创建我的测试程序testPerl pl与简单的print命令并运行它consol
  • 从具有多行记录的文件中提取数据,将每个范围保存到单独的文件中

    我有一个看起来像这样的文件 TRANSACTION STARTED 020t CARD INSERTED 020tCARD 5845 DATE 01 02 16 TIME 05 45 52 05 46 26 GENAC 1 ARQC EXT
  • 为什么选择 & 符号作为 C++ 中的引用符号? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有谁知道为什么在 C 中选择 符号作为表示引用的方式吗 AFAIK 虽然我附近没有这本书 Stroustroup 没有解释这个选择 我觉得这有点
  • Visual Studio 参考在多项目环境中未被复制

    我在 VS 2010 中有一个解决方案文件 其中有多个项目 现在 我有一个对该 dll 调用 MySql Data Entity dll 的引用 例如 我在解决方案中设置了以下项目 域 引用MySql Data Entity dll Dom
  • 如何使用“子例程引用”作为哈希键

    在 Perl 中 我正在学习如何取消引用 子例程引用 但我似乎无法使用子例程引用作为哈希 键 在下面的示例代码中 我可以创建对子例程 subref 的引用 然后取消引用它以运行子例程 subref 我可以使用引用作为哈希 值 然后轻松取消引
  • 将 stdin/stdout 从执行进程重定向到 Perl 中的管道

    我试图让执行子进程中的 STDOUT STDERR 通过 Perl 中的管道返回到父进程 我见过的最接近我想做的事情是 http forums devshed com perl programming 6 exec and redirect
  • 为什么 Perl 的 LWP 给我的编码与原始网站不同?

    可以说我有这个代码 use strict use LWP qw get my content get http www msn co il print STDERR content 错误日志显示类似 xd7 x9c xd7 x94 xd7
  • 如何在 AppleScript 的处理程序中有效地构建列表?

    AppleScript 文档建议使用以下代码来有效构建列表 set bigList to set bigListRef to a reference to bigList set numItems to 100000 set t to ti
  • PHP 指针与引用

    在 PHP 中 使用指针有什么区别 例如 function foo var var 3 a 0 foo a 以及参考 function foo var var 3 a 0 foo a 它们都修改了原始变量的值 但是它们内部的表示方式不同吗
  • Visual Studio '17 未在参考管理器中显示程序集

    我遇到的问题是 我似乎无法弄清楚如何添加对某些解决方案的引用 在我从 Visual Studio 17 开始的大多数解决方案中 我在解决方案资源管理器中看到 引用 但例如对于 asp net core web api 我得到 依赖项 每当解

随机推荐