Как мне сравнить Perl-ссылки? - PullRequest
26 голосов
/ 31 октября 2010

Я хочу проверить, указывают ли две ссылки на один и тот же объект. Кажется, я могу просто использовать

if ($ref1 == $ref2) { 
 # cheap numeric compare of references
 print "refs 1 and 2 refer to the same thing\n";
}

, как упомянуто в perlref, но я смутно помню, как видел использование некоторых функций для той же цели Есть ли причина, по которой я не должен использовать простой тест числового равенства?

Примечание. Я только хочу знать, указывают ли ссылки на один и тот же объект. Я не ищу способ сравнить содержание объекта (ов).

Ответы [ 3 ]

25 голосов
/ 31 октября 2010

Ссылки по умолчанию нумеруются по своим адресам. Эти ссылочные адреса уникальны для каждой ссылки, поэтому их часто можно использовать при проверках равенства.

Однако в показанном вами фрагменте кода сначала необходимо убедиться, что и $ref1, и $ref2 действительно являются ссылками. В противном случае вы можете получить неправильные результаты из-за обычных скаляров, содержащих адреса ссылок.

Кроме того, ничто не гарантирует ссылки на нумерацию по их адресу. Например, объекты могут использовать перегрузку, чтобы влиять на значение, которое они возвращают в различных контекстах.

Более надежный способ, чем прямое сравнение ссылок на числовое равенство, состоит в использовании функции refaddr, предоставленной Scalar::Util, после того, как обе стороны действительно являются ссылками.

16 голосов
/ 31 октября 2010

Функция, которую вы ищете, это refaddr из Scalar :: Util (после проверки того, что сравниваемые значения действительно являются ссылками):

use Scalar::Util 'refaddr';

if ($obj1 and ref($obj1) and $obj2 and ref($obj2) and
    refaddr($obj1) == refaddr($obj2))
{
    # objects are the same...
}
7 голосов
/ 31 октября 2010

Я должен предположить, что ваша #comment о том, как дешево (= быстро) тест на равенство, была там по причине.Учитывая это, вы, вероятно, должны продолжать использовать дешевый тест на равенство.Это очень быстро, намного быстрее, чем eq, не говоря уже о любом виде глубокого сравнения.

Возможно, что объект с прямо или косвенно перегруженным оператором == может узурпироватьтест для своих целей.Но если он делает это, вы можете даже предпочесть его опосредованный ответ.

Какой подход вы выберете, может зависеть от того, что вы знаете о классах объекта.Подходы, применимые к общим случаям, не всегда оптимальны для конкретных случаев.Чем больше вы знаете о чем-то, тем больше вы можете оптимизировать это - и наоборот.

Так что, если вы знаете , что вы не используете класс с применимой перегрузкой, нет никаких оснований возиться с не встроенной библиотечной функцией, и есть все основания этого не делать.Если вы не знаете о перегрузке или знаете о ней и не хотите, чтобы она применялась, возможно, используйте медленный подход.

Пока вы понимаете проблемы перегрузки,Ошибочно считать один подход правильным, а другой неправильным.У каждого своя цель.Если бы всегда было неправильно делать то, что вы делаете, то эта операция была бы либо запрещена, либо, по крайней мере, предупреждена.

Вы заметите, что не помечены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...