10

Scalar::Util::weaken言います:

注: 弱い参照をコピーすると、通常の強い参照が作成されます。

なぜ Perl がこのように処理するのか理解できません。私のアプリケーションでは、 weakenサイクルを中断するために使用します。Perl がこのように動作しなければ、すでに弱いリファレンスを弱めなければならないことがあります。

4

3 に答える 3

13

参照を新しい変数にコピーするたびに、参照カウントがインクリメントされます。これは、弱い参照または強い参照をコピーする場合に当てはまります。

my $obj = {};    # 1 reference to {} stored in $obj

my $copy = $obj; # 2 references

weaken $obj;     # 1 reference

この時点で、$copy範囲外になると、参照カウントがゼロになり、メモリが解放されます。ここで、次のコードを想定します。

my $newref = $obj;  # 2 references

undef $copy;        # 1 reference

Perl が で弱参照を保存すると、がクリアされた$newrefときにハッシュが予期せず解放されます。$copyこれは、参照をコピーすると、少なくともコピーが続く限り保持されるという期待を破ります。

要するに、代入全体で弱参照が持続する場合、無数の弱点チェックでコードを散らかさざるを得なくなり、変数の弱体化を解除する別の方法が必要になります。これらはすべて、避けられない変数の自殺の問題を回避するためです。

于 2010-12-16T21:24:06.623 に答える
10

これはカプセル化の問題だと思います。サード パーティのライブラリが内部で弱い参照を使用している場合、参照のコピーを作成すると、参照が突然消えてしまう可能性があることをコードが事前に認識しているとは限りません。Perl での通常の期待は、ref が存在する限り有効であり続けるということです。あなたが電話したとき、あなたweakenは基本的に、あなたがそれを使用する前に参照がまだ有効であることを確認するために必要な手順を踏むことを約束した.

2 つ目の理由として、弱い ref の強いコピーを弱体化するためのインターフェイスがかなり単純です。

my $new_ref = $old_ref; if (isweak($old_ref)) { weaken($new_ref); }

弱い参照が弱い参照を作成した場合に、強い参照を取得するために同じことを行うコードは、もう少し複雑です。

my $new_ref;
if (ref($old_ref) eq 'ARRAY') {
    $new_ref = \@{$old_ref};
}
elsif (ref($old_ref) eq 'HASH') {
    $new_ref = \%{$old_ref};
}
elsif (.....

ref が 1 つの型にしかならないことがわかっている場合は、if/elsifカスケードを保存して単純に deref-reref を実行できますが、新しい参照を取得するためだけに参照解除した理由を判断するのはさらに困難です。次のメンテナはあなたのコードを「修正」しようとします。

于 2010-12-16T20:01:07.930 に答える
3

これがデフォルトの動作である理由はわかりませんが、Scalar::Utilドキュメントのコードに基づくソリューションを次に示します。

$ref  = \$foo;
$weak = isweak($ref);               # false
weaken($ref);
$weak = isweak($ref);               # true

# copying a weak reference creates a new strong one
$copy = $ref;
$weak = isweak($copy);              # false

# the solution is simply to weaken the copy
$weaken($copy);
$weak = isweak($copy);              # true

弱い参照を引数として取り、その参照の弱いコピーを返すサブルーチンを作成したい場合は、上記のコードを使用すると簡単です。

于 2010-12-16T18:45:54.703 に答える