代码之家  ›  专栏  ›  技术社区  ›  Ryan Detzel

foreach my$var(@list)-$var是引用吗?

  •  8
  • Ryan Detzel  · 技术社区  · 16 年前

    所以,我从不知道这一点,我想得到一些澄清。我知道你是否知道

    foreach (@list){
    

    如果您在该循环中更改$,它将影响实际数据。但是,我不知道如果你知道的话

    foreach my $var1 (@list){
    

    如果您在循环中更改$var1,它将更改实际数据。:-/so,是否有方法循环@list,但保持变量为只读副本,或者如果更改副本,则不会更改@list中的值?

    6 回复  |  直到 11 年前
        1
  •  10
  •   Sinan Ünür    16 年前

    $var 依次为每个项目命名。

    http://perldoc.perl.org/perlsyn.html#Foreach-Loops

    如果列表中的任何元素是左值,则可以通过修改循环中的var来修改它。 相反,如果列表中的任何元素不是左值,则尝试修改该元素 会失败。换句话说,for each循环索引变量是每个变量的隐式别名 你正在循环的列表中的项目。

        2
  •  9
  •   ysth    11 年前

    最简单的方法就是复制它:

    foreach my $var1 (@list) {
        my $var1_scratch = $var1;
    

    foreach my $var1 ( map $_, @list ) {
    

    但是如果$var1是一个引用,$var1_scratch将是对同一事物的引用。 为了真正安全,您必须使用类似storable::dclone这样的工具进行深度复制:

    foreach my $var1 ( @{ Storable::dclone( \@list ) } ) {
    }
    

    (未经测试)。那么您应该能够安全地兑换$var1。但是如果 @列表是一个大数据结构。

        3
  •  4
  •   Chas. Owens    16 年前

    它是别名,而不是引用。如果要创建自己的别名(在for之外),可以使用 Data::Alias .

        4
  •  2
  •   Michael Carman    16 年前

    这些循环之间的唯一区别是:

    foreach (@array) { ... }
    foreach my $var (@array) { ... }
    

    是循环变量。别名是 foreach ,不是隐式变量 $_ . 注意这是一个 别名 (相同事物的另一个名称)而不是 参考 (指向某事物的指针)。

    在简单(和常见)情况下,您可以通过复制来破坏别名:

    foreach my $var (@array) {
        my $copy = $var;
        # do something that changes $copy
    }
    

    这适用于普通的标量值。对于引用(或对象),您需要使用 Storable Clone 可能很贵。绑定变量也是有问题的, perlsyn 建议完全避免这种情况。

        5
  •  1
  •   Sinan Ünür    16 年前

    我不知道如何在foreach语句本身中强制变量按值而不是按引用。您可以复制 $_ 不过。

    #!/usr/perl/bin
    use warnings;
    use strict;
    
    use Data::Dumper;
    
    my @data = (1, 2, 3, 4);
    
    print "Before:\n", Dumper(\@data), "\n\n\n";
    
    foreach (@data) {
        my $v = $_;
        $v++;
    }
    
    print "After:\n", Dumper(\@data), "\n\n\n";
    
    __END__
    
        6
  •  0
  •   MkV    13 年前

    在for语句中复制@list:

    foreach my $var1 (() = @list) {
      # modify $var without modifying @list here
    }