我有一个关于PHP和指针和变量的使用的问题。
下面的代码产生了一些我没有预料到的结果:
<?php
$numbers = array('zero', 'one', 'two', 'three');
foreach($numbers as &$number)
{
$number = strtoupper($number);
}
print_r($numbers);
$texts = array();
foreach($numbers as $number)
{
$texts[] = $number;
}
print_r($texts);
?>
输出如下
Array
(
[0] => ZERO
[1] => ONE
[2] => TWO
[3] => THREE
)
Array
(
[0] => ZERO
[1] => ONE
[2] => TWO
[3] => TWO
)
注意'TWO'在第二个数组中出现了两次。
两个foreach循环之间似乎存在冲突,每个循环都声明一个$number变量(一次是引用,另一次是值)。
为什么?为什么它只影响第二个foreach中的最后一个元素?
关键是PHP没有指针。它有引用,这是一个相似但不同的概念,有一些微妙的区别。
如果使用var_dump()而不是print_r(),则更容易发现:
$collection = array(
'First',
'Second',
'Third',
);
foreach($collection as &$item){
echo $item . PHP_EOL;
}
var_dump($collection);
foreach($collection as $item){
var_dump($collection);
echo $item . PHP_EOL;
}
…打印:
First
Second
Third
array(3) {
[0]=>
string(5) "First"
[1]=>
string(6) "Second"
[2]=>
&string(5) "Third"
}
array(3) {
[0]=>
string(5) "First"
[1]=>
string(6) "Second"
[2]=>
&string(5) "First"
}
First
array(3) {
[0]=>
string(5) "First"
[1]=>
string(6) "Second"
[2]=>
&string(6) "Second"
}
Second
array(3) {
[0]=>
string(5) "First"
[1]=>
string(6) "Second"
[2]=>
&string(6) "Second"
}
Second
请注意最后一个数组项中剩下的&
符号。
总而言之,无论何时在循环中使用引用,最好在末尾删除它们:
<?php
$collection = array(
'First',
'Second',
'Third',
);
foreach($collection as &$item){
echo $item . PHP_EOL;
}
unset($item);
var_dump($collection);
foreach($collection as $item){
var_dump($collection);
echo $item . PHP_EOL;
}
unset($item);
…每次输出预期的结果
变量$number
即使在循环后也被初始化,您需要通过unset
打破引用
下面的代码可以正常工作:
<?php
$numbers = array('zero', 'one', 'two', 'three');
foreach($numbers as &$number)
{
$number = strtoupper($number);
}
print_r($numbers);
unset($number);
$texts = array();
foreach($numbers as $number)
{
$texts[] = $number;
}
print_r($texts);
?>
http://www.php.net/manual/en/language.references.unset.php http://uk.php.net/manual/en/control-structures.foreach.php当你取消对引用的设置时,你只是打破了变量名和变量内容之间的绑定。这并不意味着变量内容将被销毁。
…可以把它看作类似于Unix的unlink调用。
foreach
$value的引用和最后一个数组元素即使在foreach循环之后仍然存在。建议使用unset()销毁它。
应该在第一个循环之后中断引用。
foreach($numbers as &$number)
{
$number = strtoupper($number);
}
unset($number);
如文档中所述:
$value的引用和最后一个数组元素仍然存在即使在foreach循环之后。建议通过设置().
同样,如果您使用var_dump()而不是print_r(),您会注意到第一个循环之后数组的最后一个元素是引用:
array(4) {
[0]=>
string(4) "ZERO"
[1]=>
string(3) "ONE"
[2]=>
string(3) "TWO"
[3]=>
&string(5) "THREE"
}
如果你关注Stefan Gehrig对问题的评论,有一个链接可以很好地解释这种行为:http://schlueters.de/blog/archives/141-References-and-foreach.html