Perl何时自动初始化变量?

时间:2008-11-04 02:57:10

标签: perl warnings initialization

这是一些简单的Perl来计算数组中值的出现次数。这没有任何警告。

use warnings;
use strict;

my @data = qw(1 1 2 3 4 5 5 5 9);
my %histogram;
foreach (@data)
{
    $histogram{$_}++;
}

当循环体变为

$histogram{$_} = $histogram{$_} + 1;

Perl警告“另外使用未初始化的值”。

引擎盖下发生了什么?当作为操作符提供给++运算符并且使用+运算符未初始化时,为什么值被初始化?

4 个答案:

答案 0 :(得分:15)

+运算符计算左侧的表单和右侧的表单,然后返回两者的总和。哈希调用评估没有看到任何特殊上下文。

++运算符内置了一些特殊的魔法。从perlop联机帮助页引用,关于++运算符:

  

“undef”始终被视为数字,特别是在递增之前更改为0(因此undef值的后递增将返回0而不是“undef”)。

编辑:为了详细说明差异,++改变了值,而+只是将其参数作为输入。当+看到未定义的值时,通常会出现问题,但对于++,您的哈希操作示例非常典型 - 用户希望将undef视为0,而不是每次都检查和初始化。因此,以这种方式处理这些运算符似乎是有意义的。

答案 1 :(得分:8)

并不是Perl必须初始化值,而是它并不总是警告它们。不要试图考虑这个规则,因为你总会发现异常,只要你认为它已经弄明白,下一版本的Perl就会改变你的警告。

在这种情况下,正如Harleqin所说,自动增量运算符有一个特例。

答案 2 :(得分:8)

为方便起见,某些运营商故意省略“未初始化”警告 因为它们通常用于左侧或唯一操作数的0或“”默认值有意义的情况。

这些是:++和 - (pre或post),+ =, - =,。=,| =,^ =,&& =,|| =。

请注意,其中一些错误地在绑定变量上使用时会发出警告:请参阅http://perl5.git.perl.org/perl.git/blob/HEAD:/t/op/assignwarn.t中标记为TODO的测试。

答案 3 :(得分:0)

正如布莱恩所说:它仍然这样做,它只是警告你。警告告诉您某些操作可能没有预期的效果。

您明确地询问以获取$histogram{$_}的值,向其添加1,然后将其分配到同一个广告位。这与我不希望autovivification在这里工作的方式相同:

my $hash_ref = $hash_for{$key_level_1};
$hash_ref->{$key_level_2} = $value;

就像在这里一样:

$hash_for{$key_level_1}{$key_level_2} = $value;

Magic可能不像优化那样工作。优化编译器会注意到a = a + 1a++是一样的,因此汇编语言中有增量运算符,它可以使用该优化指令而不是假装它需要保留第一个值,然后覆盖它,因为它实际上并不需要。

优化是额外的审查和开销一次,以提高每次运行的性能。但是,动态语言无法保证您不会以与尝试减少开销相同的速率增加开销。