15

我在阅读如何访问 Perl 哈希的引用计数?, 并且两者都Devel::Refcount::refcountDevel::Peek::SvREFCNT建议。

但它们不会返回相同的引用计数。这是为什么?

这是一个修改后的示例perldoc Devel::Refcount

use Devel::Peek;
use Devel::Refcount;

my $anon = [];

printf "Anon ARRAY $anon has %d/%d reference\n",
    Devel::Refcount::refcount($anon),
    Devel::Peek::SvREFCNT($anon);

my $otherref = $anon;

printf "Anon ARRAY $anon now has %d/%d references\n",
    Devel::Refcount::refcount($anon),
    Devel::Peek::SvREFCNT($anon);

打印出来:

Anon ARRAY ARRAY(0x8b10818) has 1/1 reference
Anon ARRAY ARRAY(0x8b10818) now has 2/1 references

注意最后的 2/1 差异...

(如果事实证明我没有做愚蠢的事情,我将添加一个链接,从How can I access the ref count of a Perl hash?到这里)

4

2 回答 2

10

我不能说我已经完全理解了,但是你的问题在Devel::Refcountperldoc中得到了突出的回答

与 SvREFCNT 的比较

此函数与 Devel::Peek::SvREFCNT 的不同之处在于 SvREFCNT() 给出了它所传递的 SV 对象本身的引用计数,而 refcount() 给出了被指向对象的计数。这也允许它给出任何引用的计数(即 ARRAY、HASH、CODE、GLOB 和 Regexp 类型)。

考虑以下示例程序:

 use Devel::Peek qw( SvREFCNT );
 use Devel::Refcount qw( refcount );

 sub printcount
 {
    my $name = shift;

    printf "%30s has SvREFCNT=%d, refcount=%d\n",
       $name, SvREFCNT($_[0]), refcount($_[0]);
 }

 my $var = [];

 printcount 'Initially, $var', $var;

 my $othervar = $var;

 printcount 'Before CODE ref, $var', $var;
 printcount '$othervar', $othervar;

 my $code = sub { undef $var };

 printcount 'After CODE ref, $var', $var;
 printcount '$othervar', $othervar;

这会产生输出

            Initially, $var has SvREFCNT=1, refcount=1
      Before CODE ref, $var has SvREFCNT=1, refcount=2
                  $othervar has SvREFCNT=1, refcount=2
       After CODE ref, $var has SvREFCNT=2, refcount=2
                  $othervar has SvREFCNT=1, refcount=2

在这里,我们看到 SvREFCNT() 计算作为标量值传入的 SV 对象的引用数 - 分别是 $var 或 $othervar,而 refcount() 计算指向引用对象的引用值的数量 -在这种情况下是匿名数组。

在构造 CODE 引用之前,$var 和 $othervar 的 SvREFCNT() 都为 1,因为它们仅存在于当前词法填充中。匿名 ARRAY 的 refcount() 为 2,因为 $var 和 $othervar 都存储了对它的引用。

构造 CODE 引用后,$var 变量现在的 SvREFCNT() 为 2,因为它也出现在新匿名 CODE 块的词法填充中。

于 2012-07-05T16:09:05.260 回答
5

Devel::Refcount::refcount($anon)返回由 引用的引用计数$anon

该数组由$anon和引用$otherref:2


Devel::Peek::SvREFCNT($anon)返回自身的引用计数$anon

标量由它所在的焊盘引用:1

Devel::Peek 似乎没有提供获取数组、散列等的引用计数的方法。


$ perl -MDevel::Peek -E'my $aref2 = my $aref1 = []; Dump($aref1);'
SV = IV(0x99eee34) at 0x99eee38
  REFCNT = 1                    <---- Devel::Peek::SvREFCNT
  FLAGS = (PADMY,ROK)
  RV = 0x99d57d0
  SV = PVAV(0x99d6778) at 0x99d57d0
    REFCNT = 2                  <---- Devel::Refcount::refcount
    FLAGS = ()
    ARRAY = 0x0
    FILL = -1
    MAX = -1
    ARYLEN = 0x0
    FLAGS = (REAL)

Perl 提供了一个半支持的内置调用Internals::SvREFCNT,它适用于标量、数组和散列。

Internals::SvREFCNT(@$anon)返回自身的引用计数@$anon

该数组由$anon和引用$otherref:2

以上仅适用于标量、数组和散列,您需要使用正确的印记。如果您只想传递任意引用,可以使用:

&Internals::SvREFCNT($anon) + 1返回由 引用的引用计数$anon

该数组由$anon和引用$otherref:2

于 2012-07-05T16:04:29.267 回答