在 Perl 中,foreach 循环允许方便地遍历数组元素,循环变量默认情况下 ($_ 或者显式指定的) 引用 数组元素,而不是复制它的值。
示例:
my @arr = (1, 2, 3); foreach my $x (@arr) { $x *= 2; } # @arr 变为 (2, 4, 6) — 元素已被修改!
要获取值的副本(而不是对原始元素的引用),需要显式赋值给变量:
foreach my $x ( @arr ) { # $x 是对元素的引用 ... } # ↓↓↓↓ foreach (@arr) { my $copy = $_; ... } # $copy 是副本,$_ 是对元素的引用
不应在多个嵌套的 foreach 循环中使用同一个变量,否则可能会得到意想不到的副作用。
在 foreach 循环中的变量是否是独立的副本?可以在循环体内安全地进行修改吗?
通常的回答是:"可以,因为循环会自动创建变量 — 可以随意修改。"
正确答案:
在 Perl 中,默认情况下循环变量(例如,foreach $var (@arr))是数组元素的 别名(引用)。对循环变量的任何修改都会改变原始元素!
要修改临时副本 — 在循环内显式赋值:
foreach my $elem (@arr) { my $t = $elem; $t++; # 仅是副本,原始数组不变 }
历史
历史 1
在记录过滤任务中,程序员修改了循环变量,而未意识到影响原始数据。后续计算基于修改后的数组进行,因此元素的总和计算不正确。该错误只有在与参考样本对比时才显现。
历史 2
嵌套的 foreach 使用了同一个变量($item)。内部循环的变量覆盖了外部的状态,导致第一轮的结果丢失,并且数组的一部分出现了不正确的值。
历史 3
一组指向哈希的引用通过 foreach 进行遍历,在每次循环中循环变量被赋予了新值。结果导致引用被“破坏” — 本应是引用的值现在变为标量,下一步处理因类型错误而失败。