所以,我从来不知道这一点,我想澄清一下。我知道如果你这样做
foreach (@list){
如果您在该循环中更改 $_ ,它将影响实际数据。但是,我不知道如果你这样做了
foreach my $var1 (@list){
如果您在循环中更改了 $var1 ,它将更改实际数据。:-/ 那么,有没有办法循环 @list 但将变量保留为只读副本,或者如果更改不会更改 @list 中的值的副本?
$var
依次为每个项目起别名。
请参阅http://perldoc.perl.org/perlsyn.html#Foreach-Loops
如果 LIST 的任何元素是左值,您可以通过修改循环内的 VAR 来修改它。相反,如果 LIST 的任何元素不是左值,则任何修改该元素的尝试都将失败。换句话说,foreach 循环索引变量是您正在循环的列表中每个项目的隐式别名。
最简单的方法就是复制它:
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。但是如果@list 是一个大数据结构,它可能会很昂贵。
它是别名,而不是参考。如果您想创建自己的别名(在 for 之外),您可以使用Data::Alias。
这些循环之间的唯一区别:
foreach (@array) { ... }
foreach my $var (@array) { ... }
是循环变量。别名是 的函数foreach
,而不是隐式变量$_
。请注意,这是别名(同一事物的另一个名称)而不是引用(指向事物的指针)。
在简单(和常见)的情况下,您可以通过复制来打破别名:
foreach my $var (@array) {
my $copy = $var;
# do something that changes $copy
}
这适用于普通的标量值。对于引用(或对象),您需要使用Storable或Clone进行深层复制,这可能会很昂贵。绑定变量也是有问题的,perlsyn建议完全避免这种情况。
我不知道如何在 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__
在 for 语句中复制@list:
foreach my $var1 (() = @list) {
# modify $var without modifying @list here
}