Whenever a non-existing hash or array element is used in anything but a simple context, it's autovivificated. The *default* is to autovivificate - it's just that the exceptions happen to be the most often used cases, so it's a surprise when perl autovivifies.
#!/usr/bin/perl
use strict;
use warnings;
my %hash;
sub X {}
my $x;
$x = exists $hash{key1};
printf "key1 %sautovivified\n", exists $hash{key1} ? "" : "not ";
$x = $hash{key2};
printf "key2 %sautovivified\n", exists $hash{key2} ? "" : "not ";
$x = exists $hash{key4}{key3};
printf "key3 %sautovivified\n", exists $hash{key4}{key3} ? "" : "not
+";
printf "key4 %sautovivified\n", exists $hash{key4} ? "" : "not ";
($x) = @hash{key5};
printf "key5 %sautovivified\n", exists $hash{key5} ? "" : "not ";
($x) = @hash{"key6", "key7"};
printf "key6 %sautovivified\n", exists $hash{key6} ? "" : "not ";
printf "key7 %sautovivified\n", exists $hash{key7} ? "" : "not ";
X($hash{key8});
printf "key8 %sautovivified\n", exists $hash{key8} ? "" : "not ";
X(@hash{key9});
printf "key9 %sautovivified\n", exists $hash{key9} ? "" : "not ";
X(@hash{"keyA","keyB"});
printf "keyA %sautovivified\n", exists $hash{keyA} ? "" : "not ";
printf "keyB %sautovivified\n", exists $hash{keyB} ? "" : "not ";
__END__
key1 not autovivified
key2 not autovivified
key3 not autovivified
key4 autovivified
key5 not autovivified
key6 not autovivified
key7 not autovivified
key8 not autovivified
key9 autovivified
keyA autovivified
keyB autovivified