我应该保护子程序的字符串吗?

时间:2014-07-24 14:00:32

标签: string perl

如果我有一个已定义为字符串的变量,

my $x = "abc";
sub p { ... }

然后我必须p("$x")还是p($x)p($hash->{x})

我的测试中都有效。没有引用的任何缺点?

2 个答案:

答案 0 :(得分:8)

p($x)p($hash->{x})没问题。当你执行

时,你已经复制了变量
my ($x) = @_;

my $x = shift;

无需在来电者一方创建副本(使用"$x")。


如果你没有复制元素,如果更改了sub中的全局变量,你可能会遇到问题,并且你也将该全局变量作为参数传递给sub。

$ perl -E'
   my $x;
   sub f { $x = "def"; say $_[0] }
   $x = "abc";
   say $x;
   f($x);
'
abc
def

但你为什么要那样做?这个似是而非的例子我可以想到以下几点:

$ perl -E'
   sub f { "def" =~ /(.*)/s; say $_[0] }
   "abc" =~ /(.*)/s;
   say $1;
   f($1);
'
abc
def

所以也许f("$1")有时候会有意义,但那是关于它的。

答案 1 :(得分:8)

无论是否将其用作子例程调用参数,引用单个标量变量通常被认为是不好的做法,如"$s"中所述,原因有两个

  • 您不必要地将值重复

  • 您可能正在调用重载的 stringify 行为

当然,第二个也可能是选择这样做的一个很好的理由,因为你想要使用stringify特殊行为。

使用裸变量作为子例程参数的唯一缺点是,由于Perl通过引用传递值,因此可以在子例程中修改该值。但是,您需要修改@_的元素,这是非常难以做到的。

子程序的通常形式是这个

sub proc {
  my ($p1, $p2, $p3) = @_;
  # Do stuff with $p1, $p1, $p3
}

在这种情况下,您正在使用参数的安全副本,并且修改它们对实际参数没有影响