鉴于此Perl代码:
sub a{
my $variable = $_[0];
}
$ variable的内容与$_[0]
的内容相同。它不会因变量的寿命而改变。
对赋值的解释是否会阻止Perl为$_[0]
的内容创建两个内存位置?
答案 0 :(得分: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
,因为sub返回$variable
。)
my $variable
没有被优化掉,因为无法优化分配,因为它可能会产生魔法算法的副作用。
魔法变量附加了代码。例如,当您从中读取代码时会调用代码(例如,从$ENV{PATH}
获取转换为getenv
,并存储,putenv
)。我想你可以评估$_[0]
作为赋值,然后从堆栈中清除结果,但是删除不应该存在的代码需要做很多工作。
如果您想查找未使用的词汇,请使用perlcritic
。
答案 1 :(得分:1)
赋值运算符=
始终¹复制值。这意味着如果$_[0]
包含一个非常大的字符串,那么$variable
将包含另一个完全独立的非常大的字符串。
如果这困扰你,你可以使用引用:
my $reference = \$_[0];
# the value can be accessed as $$reference
<子> 1。除非分配右侧的值无论如何都会被丢弃。
答案 2 :(得分:1)
从概念上讲,正常分配总是会对数据进行浅层复制。
“浅”,我的意思是当my $foo = \@array
是对数组的引用时,my $bar = $foo
使$bar
成为对同一数组的不同引用,所以当您push @$bar, $quux
,您追加到与push @$foo, $quux
时相同的数组,但如果您执行$bar = \@another_array
,则$foo
仍然指向原始数组。
通过“从概念上讲”,我的意思是你可以这样想。作为优化,Perl偶尔会将两个变量保存在内存的同一部分中,直到您尝试修改它们为止。这称为“写时复制”。但除非你比大多数XS代码深入挖掘,否则你应该永远不会注意到它的发生。
但是,您可以使用多个变量来引用相同的数据。这些通常被称为“别名”。在foreach
,grep
和map
块中,$_
变量(或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);
最后,也可以在小心使用绑定变量的情况下伪造别名。
答案 3 :(得分:-1)
我不明白你的意思是两个容器。标量如何有两个项目?
请注意:$_[0]
是调用函数中第一个参数的别名。如果第一个参数是变量,并且$_[0]
发生了变化,则调用代码中变量的值会发生变化。
#!/usr/bin/env perl
use strict;
use warnings;
sub a {
$_[0] = 1;
}
my $var = 0;
a( $var );
print "$var\n";