我正在 perl 5.34.0 中創建一個哈希陣列:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use autodie ':default';
use DDP;
my (@a1, @a2);
my %h = ('a' => 1);
push @a1, \%h; # make @a1 a hash of array with 'a' defined
$h{b} = 2; # define b within the hash, but don't write to @a1
push @a2, \%h; # push `a` and `b` onto @a2, but *not* @a1
p @a1; # DDP gives "p" which pretty-prints
p @a2;
這輸出:
[
[0] {
a 1,
b 2
}
]
[
[0] {
a 1,
b 2
}
]
問題是b密鑰顯示在 中@a1,但$h{b}在寫入資料時不存在@a1。
我不想b出現@a1,也不應該出現。
如何修改%h以使其不會神奇地出現在不同的陣列中?
uj5u.com熱心網友回復:
該代碼添加了對現有(命名)哈希的參考,
push @a1, \%h;
因此,當稍后查詢時,您會看到當時在哈希中看到的任何內容。陣列只攜帶一個帶有資料地址的指標,也由散列參考;這是一種別名。因此,如果同時寫入了哈希,那么您將通過@a1. ?
再次添加,即使哈希值發生變化,您只需添加相同的舊參考。
你想要的是制作一個資料副本并添加一個對它的參考——一個匿名哈希
push @a1, { %h }; # but may need deep copy instead
現在散列資料被復制以填充由 構造的匿名散列{},我們有獨立的資料,只能通過在@a1.
但請注意,如果該散列中的值本身是參考,那么這些參考會被復制,我們會遇到同樣的問題!在這種情況下,您需要一個深拷貝,最好使用庫來完成;Storable::dclone是個好人
use Storable qw(dclone);
push @a1, dclone \%h;
現在所有的實際資料都被復制,對于(參考)一個獨立的資料副本 @a1
一個重要的例外,經常使用
foreach my $elem (@ary) {
my %h;
# ... code that does its work and populates the hash ...
push @res, \%h;
}
現在,這是確定的,因為散列%h得到在每次迭代重新建立,正在申報的回圈中。那么在上一次迭代中創建的資料會發生什么?
因為它的參考被添加到一個陣列中,所以資料本身被保留,被陣列中的那個參考參考,并且只能由那個參考參考。正是您想要的,只能通過陣列訪問的單獨資料。
在這種情況下,這優于push @res, { %h },這也有效,因為在保留資料的同時避免了資料復制,可以說,僅僅改變其所有權。
?并且 ff 資料通過 更改@a1,例如$a1[0]->{key} = 'val';,然后也可以通過 看到新值$h{key}。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/337143.html
標籤:perl
