当变量被赋值为另一个变量时,数据是否存储在一个位置,而第二个值不变?

时间:2013-08-03 14:12:55

标签: perl

鉴于此Perl代码:

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

$ variable的内容与$_[0]的内容相同。它不会因变量的寿命而改变。

对赋值的解释是否会阻止Perl为$_[0]的内容创建两个内存位置?

4 个答案:

答案 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代码深入挖掘,否则你应该永远不会注意到它的发生。

但是,您可以使用多个变量来引用相同的数据。这些通常被称为“别名”。在foreachgrepmap块中,$_变量(或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";