Но они не возвращают одинаковые счетчики ссылок. Это почему?
Вот модифицированный пример из 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...
Я не могу сказать, что я все это уже понял, но ответ на ваш вопрос хорошо виден в Devel::Refcount perldoc
СРАВНЕНИЕ С 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.
Ответ 2 · рейтинг 5 · ikegami
Devel::Refcount::refcount($anon) возвращает счетчик ссылок того, на что ссылается $anon.
На массив ссылаются $anon и $otherref: 2
Devel::Peek::SvREFCNT($anon) возвращает счетчик ссылок самого $anon.
На скаляр ссылается блокнот, в котором он находится: 1
Devel::Peek, похоже, не предоставляет средств для получения количества ссылок на массивы, хэши и т.д.
Perl предоставляет частично поддерживаемую встроенную функцию Internals::SvREFCNT, которая работает со скалярами, массивами и хэшами.
Internals::SvREFCNT(@$anon) возвращает счетчик ссылок самого @$anon.
На массив ссылаются $anon и $otherref: 2
Вышеупомянутое работает только для скаляров, массивов и хэшей, и вам нужно использовать правильный сигил. Если вы просто хотите передать произвольную ссылку, вы можете использовать:
&Internals::SvREFCNT($anon) + 1 возвращает счетчик ссылок того, на что ссылается $anon.