【发布时间】:2016-05-16 08:53:14
【问题描述】:
在 Perl 中,如何检查两个不同可变对象的指针是否相等?
由于在 Perl 中几乎所有内容都是可变的,因此有时可能需要知道两个对象何时相同——也就是说,修改一个对象会影响另一个对象。怎么可能做到这一点?
编辑:“对象”是指任何 Perl 值。这包括字符串、数组、哈希等。
【问题讨论】:
标签: perl
在 Perl 中,如何检查两个不同可变对象的指针是否相等?
由于在 Perl 中几乎所有内容都是可变的,因此有时可能需要知道两个对象何时相同——也就是说,修改一个对象会影响另一个对象。怎么可能做到这一点?
编辑:“对象”是指任何 Perl 值。这包括字符串、数组、哈希等。
【问题讨论】:
标签: perl
如果您知道这两个值都是引用,则可以使用数字相等运算符== 来比较它们。
如果您不确定这两个值都是引用,您可以先使用ref 对其进行测试。
if (ref($x) and ref($y) and $x==$y) {
print "\$x and \$y are references to the same thing.\n"
}
这记录在perlref 中,上面写着
如上所述,使用字符串或数字作为引用会产生符号引用。将引用用作数字会生成一个整数,表示其在内存中的存储位置。这样做的唯一有用的事情是在数字上比较两个引用以查看它们是否引用相同的位置。
【讨论】:
*a=\@b 之类的东西使不同的名称引用同一个数组。在那种情况下,我认为您仍然可以使用参考比较:\@a == \@b
有时可能需要知道两个对象何时相同——也就是说,修改一个对象会影响另一个对象。怎么可能做到这一点?
以下是使用此类检查的示例:
*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 示例无法突出显示语法:)