最近面试多,基本上一天一面试。遇到一个关于php赋值传值、引用传值及unset的问题,以前没有深究,百度了下发现道道还不少。

面试题:请问以下输出的结果是?

  1. Class User {  

  2. public $name;  

  3. }  

  4. $user1 = new User();  

  5. $user2 = $user1;  

  6. $user1 -> name = 'one';  

  7. $user2 -> name = 'two';  

  8.   

  9. $array1 = array();  

  10. $array2 = $array1;  

  11. $array1['name'] = 'one';  

  12. $array2['name'] = 'two';  

  13.   

  14. echo $user1->name;//two  

  15. echo $user2->name;//two  

  16. echo $array1['name'];//one  

  17. echo $array2['name'];//two  

  18. //个人理解是,对象默认传值方式是引用传值,所以前面2个输出two  

  19. //而下面2个传值方式是赋值传值,所以各不影响。  

 

二篇相关文章,值得一读:
 

篇一:PHP的赋值传值与引用传值以及unset

首先,要理解变量名存储在内存栈中,它是指向堆中具体内存的地址,通过变量名查找堆中的内存;
普通传值,传值以后,是不同的地址名称,指向不同的内存实体;
引用传值,传引用后,是不同的地址名称,但都指向同一个内存实体;改变其中一个,另外一个就也被改变;

以下我将通过三个列子来详细讲解这两个传值的区别:

Example1:

  1. //普通传值  

  2. $param1=1;   

  3. $param2=2;   

  4. $param2 = $param1;   

  5. $param1 = 5; //变量1和变量2是两块内存,互不影响;  

  6. echo $param2//所以此处还是显示为1  

  7.   

  8. //引用传值 ↓↓  

  9. $param1=1;   

  10. $param2=2;   

  11. $param2 = &$param1//把变量1的内存地址赋给变量2;此时的变量2和变量1全等;  

  12. echo $param2;// 1  

  13. $param1 = 5; //变量1和变量2是一处内存,改变其中一个,另外一个也被改变;  

  14. echo $param2//显示为5  

 

Example2:

  1. //函数中的普通传值 ↓↓  

  2. $param1 = 1;   

  3. function add($param2){  

  4.   $param2=3;   

  5. }  

  6. $param3=add($param1); //调用方法add,并将变量1传给变量2,此处是普通传值,所以变量1和变量2是两处内存,互不影响;  

  7. echo '<br>$param1=='.$param1.'<br>'; //显示为$param1==1  

  8. echo '<br>$param2=='.$param2.'<!-- <br> -->'; //显示为$param2== 因为$param2是局部变量,函数运行完了以后就自动销毁,其不能影响全局  

  9.   

  10. //函数中的引用传值 ↓↓ 注意,php不建议这样使用,并且php.in里面设置其会报错;  

  11. $param1 = 1;   

  12. function add($param2){  

  13.   $param2=3;   

  14.   return $param2;  

  15. }  

  16. $param3=add(&$param1); //调用方法add,并将变量1的引用传给变量2,此时两个地址指向同一内存,改变其中一个,另外一个也要被改变;  

  17. echo $param1//3,内存已在函数内部改变;  

  18. echo $param3//3   

 

Example3:

  1. //给数组里面的键值各增加10;  

  2. $arr = array(3,5);  

  3.   

  4. foreach($arr as $k=>$v){  

  5.  $v+=10;//1.更改无效,相当于遍历出的键值扔给变量$v,然后更改变量$v的值,跟数组无关;  

  6.  echo $v." ";//输出13 15;  

  7. }  

  8.   

  9. foreach($arr as $k=>$v){  

  10.   $arr[$k]+=10;//2.更改有效,直接更改键名里面的值;  

  11.   echo $v;//输出3,5;  

  12.  }    

  13.   

  14. foreach($arr as &$v){  

  15.   $v+=10;//3.更改有效,遍历的键值直接给了$v的地址,这个地址其实就是键名..$v+10就等于$arr[$k]+10;  

  16. }   

 

然后我们来看一下这道面试题:

  1. $a = 1;  

  2. $b = &$a;  

  3. unset($a);  

  4. echo $b//??  

 

注意: unset并没有真正销毁变量的作用...仅仅是切断了变量与内存之间的关系,内存只要还被引用着就不会被释放; $b和$a同时指向1,切断其中$a的关系,$b还是指向1,所以上题不报错,照样输出1。

另外补充一点: 在PHP中对象的传值默认是引用传值

再看一题:

在做这题之前我们回顾一下什么是析构函数,而PHP中对象销毁的方式有哪些:

析构函数:对象销毁时执行;注意在隐式销毁中是在是所有php代码执行完最后一行代码的时候才销毁,还有要注意在单入口文件下的MVC模式

对象的销毁

  1. 显试销毁: 当对象没有被引用时就会被销毁,所以我们可以unset或为其赋值NULL;

  2. 隐试销毁:PHP是脚本语言,在代码执行完最后一行时,所有申请的内存都要释放掉.

Example1:

  1. class Human {   

  2.   public $name = '张三';   

  3.   public $gender = null;   

  4.   public function __destruct() {   

  5.       echo '死了!<br />';   

  6.   }   

  7. }   

  8. $a = new Human();   

  9. $b = $c = $d = $a;  

  10. unset($a);    

  11. echo '<hr />';  //析构函数究竟是触发了几次,是在线上触发,还是在线下触发?  

 

答案:

$b = $c = $d = $a;默认引用传值,四个变量指向同一处内存,unset的时候对象还是被还是其它三个变量使用,所以对象并没有被销毁,所以析构函数是在线下触发的(代码执行完了,内存自动释放)


评论(0条)

刀客源码 游客评论