【问题标题】:How can I check for reference equality in Perl?如何在 Perl 中检查引用相等性?
【发布时间】:2016-05-16 08:53:14
【问题描述】:

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

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

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

【问题讨论】:

    标签: perl


    【解决方案1】:

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

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

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

    这记录在perlref 中,上面写着

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

    【讨论】:

    • 我也想知道两个数组是不是同一个数组,两个hash是同一个hash等等
    • 您是否经常遇到同一个数组但名称不同的数组?我认为通常这只会提供参考。当然,可以使用 *a=\@b 之类的东西使不同的名称引用同一个数组。在那种情况下,我认为您仍然可以使用参考比较:\@a == \@b
    • 注意:这不适用于重载数字化的对象
    • 注意:要检查一个变量是否会改变另一个变量,还需要检查魔术
    • 如果你有两个数组,你不想只检查数组是否相同,而是检查它们是否共享任何元素。
    【解决方案2】:

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

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

    *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

    您不仅要检查两个“对象”是否相同,还要检查它们是否具有魔力。在上面的示例中,检查 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 ]);
    

    【讨论】:

    • 不确定是否重要,只是指出这些perl -E 示例无法突出显示语法:)
    猜你喜欢
    • 1970-01-01
    • 2015-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-24
    • 1970-01-01
    相关资源
    最近更新 更多