转子:http://blog.csdn.net/ohmygirl/article/details/8726865
朋友昨天去金山面试PHP开发时遇到的一道面试题,是关于引用和foreach循环的。很基础的一道题
废话不多说,直接看代码:
- $a = array('a','b','c');
- foreach($a as &$v){}
- foreach($a as $v){
- }
- var_dump($a);
对引用比较了解的童鞋可能已经看出来了。正确答案是: array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> &string(1) "b"} 也就是a,b,b. 如果你猜测的是a,b,c的话。 那么关于引用,你还要查阅一下相关的资料:http://www.php.net/manual/zh/language.references.php
那么为什么是a,b,b呢。让我们一步步来看:
我们知道对数组执行foreach循环时,是通过移动数组内部指针来实现的(关于更多细节,可以阅读php源码)。因而对于本文中的例子:当foreach循环结束的时候,由于$v为
引用变量,因而$v 与 $a[ 2 ] 指向了同一个地址空间(共享变量值),因而之后对$v的任何修改都会直接反映到数组$a中。我们可以对例子加上调试代码,便会一清二楚,例如我们在第二次循环内部,加上var_dump($a),测试每次循环时a的值的变化:
- $a = array('a','b','c');
- foreach($a as &$v){}
- foreach($a as $v){
- var_dump($a);
- echo "<br/>";
- }
- var_dump($a);
- array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> &string(1) "a" }
- array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> &string(1) "b" }
- array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> &string(1) "b" }
- array(3) { [0]=> string(1) "a" [1]=> string(1) "b" [2]=> &string(1) "b" }
画个图:可以更加清晰看出来:(图中"$v指向了$a[2]"并不准确。应该是:$v与$a[2]指向了同一个地方)
关于引用的几点简单解释:
1.引用类似于指针,但是不同于指针。
例如对于引用:
- $a = "str";
- $b = &$a;//<var class="varname"><var class="varname"> $a</var></var> 和 <var class="varname"><var class="varname">$b</var></var> 指向了同一个地方
一个简单的示意图如下:
那么此时更改$a和$b中任何一个元素的值。另外一个值都为随之改变:
- $a = "str";
- $b = &$a;
- $b = "sssss";
- echo $a;
2.unset只会删除变量。并不会清空变量值对应的内存空间:(这是与指针不同的地方)
- $a = "str";
- $b = &$a;
- unset($b);
- echo $a;
3.引用作为函数参数传递时,是可以被函数内部更改的:
- function change(&$a){
- if(is_array($a)){
- $a = array();
- }
- }
- $test = range(1,10);
- change($test);
- print_r($test);
基于以上几点,在编码的过程中,要小心使用引用。防止陷入莫名其妙的尴尬。
ps:理解了么?试试这道题:
- $a = range(1,3);
- foreach($a as &$b){
- $b *= $b;
- }
- foreach( $a as $b){
- echo $b;
- }
猜猜看,输出是什么?。
144