1

Given this Perl code:

sub a{
my $variable = $_[0];
}

The content of $variable is the same as that of $_[0]. It doesn't change for the life-span of the variable.

Does interpretation of the assignment prevent Perl from creating two memory locations for the contents of $_[0]?

4

4 回答 4

4

不清楚你的意思,但有两个“容器”。$_[0]并且传递给函数的参数由一个组成。my $variable创建另一个。赋值不会创建容器/标量/变量。


根据评论,您的问题似乎实际上是关于是否my $variable和/或分配被优化掉。他们不是。

>perl -MO=Concise,-exec,a -e"sub a { my $variable = $_[0]; return; }"
main::a:
1  <;> nextstate(main 1 -e:1) v
2  <#> aelemfast[*_] s
3  <0> padsv[$variable:1,2] sRM*/LVINTRO   <-- my $variable
4  <2> sassign vKS/2                       <-- scalar assignment in void context
5  <;> nextstate(main 2 -e:1) v
6  <0> pushmark s
7  <@> return K
8  <1> leavesub[1 ref] K/REFC,1
-e syntax OK

(我添加了return因为子返回,$variable否则。)

my $variable没有被优化掉,因为分配不能被优化掉,因为它可能对神奇的 args 有副作用。

魔法变量附有代码。例如,当您从它们中读取代码时(例如,从$ENV{PATH}翻译到getenv和存储putenv),将调用该代码。我想您可以$_[0]像赋值一样进行评估,然后从堆栈中清除结果,但是要删除不应该存在的代码需要做很多工作。

如果要查找未使用的词汇,请使用perlcritic.

于 2013-08-03T14:19:00.750 回答
1

赋值运算符= 总是¹ 复制值。这意味着如果$_[0]包含一个非常大的字符串,那么$variable将包含另一个完全独立的非常大的字符串。

如果这让您感到困扰,您可以使用参考:

my $reference = \$_[0];
# the value can be accessed as $$reference

1.除非赋值右侧的值无论如何都会被丢弃。

于 2013-08-03T14:19:26.947 回答
1

从概念上讲,正常的赋值总是对数据进行浅拷贝。

通过“浅”,我的意思是 whenmy $foo = \@array是对一个数组的引用,然后对同一个数组my $bar = $foo进行$bar不同的引用,所以当你时push @$bar, $quux,你会像你时一样附加到同一个数组push @$foo, $quux,但是如果你这样做$bar = \@another_array,那么$foo仍然指向原始数组。

“从概念上讲”,我的意思是你可以这样想。作为一种优化,Perl 偶尔会将这两个变量保存在内存的同一部分,直到您尝试修改一个。这称为“写时复制”。但是,除非您比大多数 XS 代码深入挖掘,否则您永远不应该注意到它的发生。

但是,在某些情况下,您可以有多个变量引用相同的数据。这些通常被称为“别名”。在foreach,grepmap块中,$_变量(或 的情况下的另一个词法变量foreach)是当前正在处理的项目的别名:

foreach my $foo ($bar, $baz) {
    # In here, $foo is an alias for $bar, then $baz.
    # When $foo is aliased to $bar, then modifiying $foo
    # also modifies $bar, and vice versa.
}

也可以通过分配给 glob 来创建别名。这是一个例子:

our $foo;
my $bar = 19;
*foo = \$bar;        # alias $foo to $bar
$foo++;
$bar++;
print $foo + $bar;   # 42

注意$foo有一个包变量(our);glob 赋值仅适用于包变量。但是 Data::Alias 和 Devel::LexAlias 允许你用词法变量 ( my) 做类似的事情。

出现别名的另一种情况是@_subs 中的数组。这里:

sub quux {
    # In here, $_[0] is an alias for $foo
    # In here, $_[1] is an alias for $bar
}

quux($foo, $bar);

最后,别名也可以通过谨慎使用绑定变量来伪造。

于 2013-08-03T23:27:18.227 回答
-1

我不明白你说的两个容器是什么意思。一个标量怎么可能有两个项目?

请注意:$_[0]是调用函数中第一个参数的别名。如果第一个参数是一个变量,并且$_[0]是变化的,那么调用代码中变量的值就会改变。

#!/usr/bin/env perl

use strict;
use warnings;

sub a {
  $_[0] = 1;
}

my $var = 0;
a( $var );
print "$var\n";
于 2013-08-03T15:09:37.793 回答