如何检查Perl中的引用相等性?

时间:2016-05-13 23:03:01

标签: perl

在Perl中,我如何检查两个不同的可变对象的指针相等性?

由于在Perl中几乎所有东西都是可变的,因此有时可能需要知道两个对象何时相同 - 也就是说,修改一个对象会影响另一个对象。怎么能这样做?

编辑:“对象”是指任何Perl值。这包括字符串,数组,哈希等。

2 个答案:

答案 0 :(得分:7)

如果您知道这两个值都是引用,则可以使用数字相等运算符==来比较它们。

如果您不确定这两个值都是引用,则可以先使用ref对其进行测试。

if (ref($x) and ref($y) and $x==$y) {
  print "\$x and \$y are references to the same thing.\n"
}

perlref中记录了这一点,

  

使用字符串或数字作为参考会产生符号引用,如上所述。使用引用作为数字会生成一个整数,表示其在内存中的存储位置。要做的唯一有用的事情是用数字比较两个引用,看它们是否引用相同的位置。

答案 1 :(得分:5)

  

有时可能需要知道两个对象何时相同 - 也就是说,修改一个对象会影响另一个对象。怎么能这样做?

以下是使用此类检查的示例:

*d = \$x;              # Makes $d an alias for $x.
($x, $y) = ($y, $x);   # Requires creating temporary copies.
($x, $y) = ($m, $n);   # Usually simple ($x=$m; $y=$m;)
($x, $y) = ($c, $d);   # Requires creating temporary copies.

您可以看到检查here

您不仅要检查两个"对象还是#34;是相同的,你想检查他们是否神奇。在上面的例子中,检查LHS上的变量" set"魔术,并检查RHS上的变量" get"魔法。

要检查分配给$dst是否可以更改$src,请使用以下内容:

use B            qw( svref_2object SVs_GMG SVs_SMG );
use Scalar::Util qw( refaddr );

sub SvGMAGICAL { !!( svref_2object($_[0])->FLAGS & SVs_GMG ) }
sub SvSMAGICAL { !!( svref_2object($_[0])->FLAGS & SVs_SMG ) }

sub could_be_common {
   my ($dst_ref, $src_ref) = @_;
   my $dst_addr = refaddr($dst_ref) or die("usage");
   my $src_addr = refaddr($src_ref) or die("usage");
   return $dst_addr == $src_addr || SvSMAGICAL($dst_ref) || SvGMAGICAL($src_ref);
}

say could_be_common($dst, $src);

或者对于上面的例子,

sub could_be_common {
   my ($dst_ref, $src_refs) = @_;
   for my $dst_ref (@$dst_refs) {
      return 1 if SvRMAGICAL($dst_ref);
   }

   for my $src_ref (@$src_refs) {
      return 1 if SvGMAGICAL($src_ref);
   }

   for my $dst_ref (@$dst_refs) {
      my $dst_addr = refaddr($dst_ref);
      for my $src_ref (@$src_refs) {
         return 1 if $dst_addr == refaddr($src_ref);
      }
   }

   return 0;
}

say could_be_common([ \$x, \$y ], [ \$c, \$d ]);