关于这个概念一般都会在PHP的第一堂课说变量的时候给介绍,并且我以前还给其他PHPer介绍这个概念。但是作为一个工作一段时间的PHPer的我,竟然在面试的时候一下子拿不定主意最后还答错了,很觉得丢脸(下面我会一一道来),所以就写一篇关于这个概念的博文,该概念在PHP面试中也算是常考的题吧;

首先,要理解变量名存储在内存栈中,它是指向堆中具体内存的地址,通过变量名查找堆中的内存;

普通传值,传值以后,是不同的地址名称,指向不同的内存实体;

引用传值,传引用后,是不同的地址名称,但都指向同一个内存实体;改变其中一个,另外一个就也被改变;

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

Example1:

<?php
//普通传值
$param1=1;
$param2=2;
$param2 = $param1;
$param1 = 5; //变量1和变量2是两块内存,互不影响;
echo $param2; //所以此处还是显示为1 //引用传值 ↓↓
$param1=1;
$param2=2;
$param2 = &$param1; //把变量1的内存地址赋给变量2;此时的变量2和变量1全等;
echo $param2;// 1
$param1 = 5; //变量1和变量2是一处内存,改变其中一个,另外一个也被改变;
echo $param2; //显示为5
?>

Example2:

<?php
//函数中的普通传值 ↓↓
$param1 = 1;
function add($param2){
$param2=3;
}
$param3=add($param1); //调用方法add,并将变量1传给变量2,此处是普通传值,所以变量1和变量2是两处内存,互不影响;
echo '<br>$param1=='.$param1.'<br>'; //显示为$param1==1
echo '<br>$param2=='.$param2.'<!-- <br> -->'; //显示为$param2== 因为$param2是局部变量,函数运行完了以后就自动销毁,其不能影响全局 //函数中的引用传值 ↓↓ 注意,php不建议这样使用,并且php.in里面设置其会报错;
$param1 = 1;
function add($param2){
$param2=3;
return $param2;
}
$param3=add(&$param1); //调用方法add,并将变量1的引用传给变量2,此时两个地址指向同一内存,改变其中一个,另外一个也要被改变;
echo $param1; //3,内存已在函数内部改变;
echo $param3; //3
?>

Example3:

<?php
//给数组里面的键值各增加10;
$arr = array(3,5); foreach($arr as $k=>$v){
$v+=10;//1.更改无效,相当于遍历出的键值扔给变量$v,然后更改变量$v的值,跟数组无关;
echo $v." ";//输出13 15;
} foreach($arr as $k=>$v){
$arr[$k]+=10;//2.更改有效,直接更改键名里面的值;
echo $v;//输出3,5;
} foreach($arr as &$v){
$v+=10;//3.更改有效,遍历的键值直接给了$v的地址,这个地址其实就是键名..$v+10就等于$arr[$k]+10;
}
?>

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

$a = 1;
$b = &$a;
unset($a);
echo $b; //??
当时我的回答是这样的: 会报一个notice的错误,因为$b和$a共用一处内存,unset就把这处内存销毁掉了,然后输出$b变量的时候找不内存,所以应该是Notice:  Undefined variable: b in

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

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

再看一题:

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

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

对象的销毁

  1. 显试销毁: 当对象没有被引用时就会被销毁,所以我们可以unset或为其赋值NULL;
  2. 隐试销毁:PHP是脚本语言,在代码执行完最后一行时,所有申请的内存都要释放掉.

Example1:

class Human {
public $name = '张三';
public $gender = null;
public function __destruct() {
echo '死了!<br />';
}
}
$a = new Human();
$b = $c = $d = $a;
unset($a);
echo '<hr />'; //析构函数究竟是触发了几次,是在线上触发,还是在线下触发?

答案:

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

Example2:

class Human {
public $name = '张三';
public $gender = null; public function __destruct() {
echo '死了!<br />';
}
}
$e = $f = $g = new Human();
unset($e);
unset($f);
unset($g);
echo '<hr />'; //同样的问题: 析构函数是在线上触发还是线下触发?

我相信通过Example1的讲解,应该很快知道答案是在线上触发;在代码运行完自动释放内存之前由于对象已经没有被任何变量引用所以就自动释放了内存....

最后:

其实这家面试是我第一家面试,各方面都还挺满意的,也谈妥了;但是我还是很想多面试几家,并不是为了去比价或者怎么的,很多时候我认为在面试中其实可以学到很多东西的。现在的人事小姐真的是巨能说话,架不住她的那种气场就答应早点上班了,真心想多面试几家~~唉!

从一次面试经历谈PHP的普通传值与引用传值以及unset的更多相关文章

  1. 2015腾讯暑期实习生 Web前端开发 面试经历

    [2015腾讯暑期实习生 Web前端开发 面试经历] 好吧,首先声明,我被刷了,应该是跪在二面 微信查到的面试状态一直呈现复试中 .. 整整四天了.. 看来是没希望了 不过也是一次经历,记录一下还是可 ...

  2. Unity 工作经历+近期面试经历

    由于团队解散,这最近都在找新工作机会--投简历找工作.已经面试三家了,都没拿到offer,挺失落的.把这种感受记录下来,以作后鉴. 这本质上是一篇面试经历的记录,并不是什么面试攻略,主要是给自己总结的 ...

  3. 学生党如何拿到阿里技术offer:《阿里面试经历-2014.4.18研发实习生面试经历(失败)》

    我们分享的上一篇文章是一位学长在大三的时候面试阿里实习生成功的经历的分享,其实就像学长在上一篇文章最后说的那样“面试并没有想的那么难,运气也会占一部分.”,其实我个人觉得,对于我们而言,自己越努力就会 ...

  4. java开发实习生面试经历

     这是我第一次写博客,以前都是查看别人的博客分享学习技术,转眼间我也成为其中一员.从一位初学者到现在的开发实习生,不断前进着,跟随时代的脚步在程序的海洋里漂泊,也意识到自己的各种不足,但我还年轻,头还 ...

  5. [原创]大连sap vt 实习生面试经历

    从决定参加这次面试开始,求职生涯就算是开始了,虽然失败了,但也是亲身体会到了面试的感觉,这次经历也作为第一篇博客. 大连sap的职能是sap的全球技术支持中心和解决方案提供中心.VT项目提供的岗位是技 ...

  6. IBM 中国研究院面试经历

    继上次面试MSRA失败后,严重刺激了我幼小的心灵.从此苦学算法准备面试很多其它其它的公司刷一刷Offer以解心 头之恨. 这个带来的IBM 中国研究院的面试经历. IBM的面试相比于MSRA.简直就是 ...

  7. Intel 的面试经历中国研究院

    那么今天写Intel 的面试经历中国研究院.Intel我采访了面试题比较简单的一. 第一次是在大约下午五时三十, 我正在食堂和好几个基友吃20元巨资买的清蒸草鱼.正在吐沫星子四处飞溅的时候.一个010 ...

  8. 2019年京东Java研发岗社招面经(面试经历+真题总结+经验分享)!

    本篇先以日历形式回顾秋招之路,方便各位参考某厂的处理进度:然后是总结归纳春秋招Java面试题库:最后做个总结还有展望,开始新的征程~ 面试经历京东面试真题面试经验分享1.面试经历 2018年的冬季特别 ...

  9. Android面试经历2018

    本人14年7月份出来参加工作,至今工作将近4年的时间了,坐标是深圳.由于在目前的公司,感觉没什么成长,就想换一个公司.楼主已经在从实习到现在,已经换了三家公司了,所以这次出来的目标的100人以上,B轮 ...

随机推荐

  1. 基础学习总结(七)--子线程及Handler

    使用子线程获取网络图片1.采用httpUrlConnection直连方式获取图片2.采用子线程方式获取 <LinearLayout xmlns:android="http://sche ...

  2. (一)熟悉执行流程——基于ThinkPHP3.2的内容管理框架OneThink学习

    ThinkPHP作为国内具有代表性的PHP框架,经过多年的发展,受到越来越多公司与开发者的青睐.我也在忙里偷闲中抽出部分时间,来学习这个优秀的框架.在开始学习这个框架时,最好通过实例来学习,更容易结合 ...

  3. C#函数运行超时则终止执行(任意参数类型及参数个数通用版)

    /// <summary> /// 控制函数执行时间,超时返回null不继续执行 /// 调用方法 /// FuncTimeout.EventNeedRun action = delega ...

  4. Silverlight中嵌套html、swf、pdf

    1.MainPage.xaml <UserControl x:Class="SilverlightClient.MainPage" xmlns="http://sc ...

  5. js定时器 特定时间执行某段程序的例子

    定时器想必大家并不陌生吧,在本文为大家详细介绍下js中是如何实现定时器的,具体原理及代码如下. 例子: $(function(){ var handler = function(){ //www.jb ...

  6. haproxy 安装与配置文件详解

    本文主要阐述haproxy的安装配置详解,对于它的概念,作用,功能,和其它LB软件的区别,优点,缺点等不再进行说明. 一. haproxy 的安装配置 # cat /etc/redhat-releas ...

  7. WPF学习笔记 控件篇 属性整理【1】FrameworkElement

    最近在做WPF方面的内容,由于好多属性不太了解,经常想当然的设置,经常出现自己未意料的问题,所以感觉得梳理下. ps:先补下常用控件的类结构,免得乱了 .NET Framework 4.5 Using ...

  8. Hadoop管理员的十个最佳实践(转)

    前言 接触Hadoop有两年的时间了,期间遇到很多的问题,既有经典的NameNode和JobTracker内存溢出故障,也有HDFS存储小文件问题,既有任务调度问题,也有MapReduce性能问题.遇 ...

  9. Swiper简单入门

    背景需求 给业务部分在m站实现一个邀请函的h5页面,基本流程:1.会议主题,2邀请函内容,3会议安排,4会议网络资源二维码,5酒店安排 技术分析 将ppt搬到h5上,每一页要用帧显示(这个没有用过). ...

  10. 【Go】http server 性能测试

    node秒java几街!pathon秒node几街 !go秒pathon几街! ab测试性能极佳的 package main import ( "fmt" "html/t ...