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模式
对象的销毁:
- 显试销毁: 当对象没有被引用时就会被销毁,所以我们可以unset或为其赋值NULL;
- 隐试销毁: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的讲解,应该很快知道答案是在线上触发;在代码运行完自动释放内存之前由于对象已经没有被任何变量引用所以就自动释放了内存....
原文地址: https://www.cnblogs.com/nixi8/p/4925094.html
php普通传值和引用传值 (相当通俗易懂的一篇讲解)的更多相关文章
- 从一次面试经历谈PHP的普通传值与引用传值以及unset
关于这个概念一般都会在PHP的第一堂课说变量的时候给介绍,并且我以前还给其他PHPer介绍这个概念.但是作为一个工作一段时间的PHPer的我,竟然在面试的时候一下子拿不定主意最后还答错了,很觉得丢脸( ...
- PHP的普通传值与引用传值以及unset
首先,要理解变量名存储在内存栈中,它是指向堆中具体内存的地址,通过变量名查找堆中的内存; 普通传值,传值以后,是不同的地址名称,指向不同的内存实体; 引用传值,传引用后,是不同的地址名称,但都指向同一 ...
- JS 拷贝传值和引用传值
1.拷贝传值:基本数据类型都是“拷贝传值”. 拷贝传值,就是将一个变量的值“拷贝”一份,传给了另一个变量. 拷贝传值中,两个变量之间没有任何联系,修改其中一个变量的值,另一个不会改变. 这两个变量之间 ...
- PHP变量的传值和引用
问题: 1.PHP变量的存储.取值方式如何? 2.变量赋值时,普通传值和引用传值分别是什么意思?有何区别? 3.unset被赋值的变量会对两种赋值后原值和新值的影响? 变量的存储.取值形式: 变量 ...
- Java基础必备 -- 堆栈、引用传值、垃圾回收等
在Java中,对象作为函数参数的传递方式是值传递还是引用传递?String str = "abc" 与 String str = new String("abc&quo ...
- PHP和CS的引用传值
PHP的引用传值 function change_value($num){ $num+=2; } $age = 3; change_value(&$age); echo $age; CS的引用 ...
- Js 赋值传值和引用传址
赋值传值和引用传址 在JavaScript中基本数据类型都是赋值传值,复合数据类型都是引用传址(传地址) 基本数据类型的变量名和数据是直接存在"快速内存"(栈内存)中,而复合数据类 ...
- Python引用传值总结
Python函数的参数传值使用的是引用传值,也就是说传的是参数的内存地址值,因此在函数中改变参数的值,函数外也会改变. 这里需要注意的是如果传的参数类型是不可改变的,如String类型.元组类型,函数 ...
- PHP引用传值规范问题
在我上一篇: shopnc 商城源码阅读笔记--开篇概述 中,遇到了一个PHP引用传值导致的错误,情况大致如下: 在我查阅PHP官方文档 的中文版的时候 http://php.net/ma ...
随机推荐
- APP,H5测试要点
APP测试重点 一,运行测试 运行过程中,是否有加载提示: 运行速度是否流畅: 各个模块之间的切换是否正常: 二,更新测试:打开旧版app时,是否有更新提示,且在不同的手机版本上都能更新成功:打开新版 ...
- python 爬虫与数据可视化--python基础知识
摘要:偶然机会接触到python语音,感觉语法简单.功能强大,刚好朋友分享了一个网课<python 爬虫与数据可视化>,于是在工作与闲暇时间学习起来,并做如下课程笔记整理,整体大概分为4个 ...
- Spring Cloud微服务笔记(一)微服务概念
微服务概念 一.什么是微服务架构 微服务,是一个小的.松耦合的分布式服务. 为什么需要微服务: 1)单体系统部署在一个进程中,修改了一个小功能,为了部署上线就会影响其他功能. 2)单体应用各个功能模块 ...
- ubantu安全卸载火狐浏览器
首先查看浏览器相应的安装包,命令: dpkg --get-selections |grep firefox 2.删除相面出现的包的命令: sudo apt-get purge pck1-name p ...
- Python数据分析基础教程
Python数据分析基础教程(第2版)(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1_FsReTBCaL_PzKhM0o6l0g 提取码:nkhw 复制这段内容后 ...
- ECMA Script 6_函数的扩展
ES6规定只要函数参数使用了默认值.解构赋值.或者扩展运算符, 那么函数内部就不能显式设定为严格模式,否则会报错 1. 参数的默认值 ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面 函数 ...
- Java课程课后作业190315之从文档中读取随机数并得到最大连续子数组
从我上一篇随笔中,我们可以得到最大连续子数组. 按照要求,我们需要从TXT文档中读取随机数,那在此之前,我们需要在程序中写入随机数 import java.io.File; import java.i ...
- amazeui表单form异步提交方法
// 留言提交 $(function() { var $form = $('#ue-form'); $form.validator({ validateOnSubmit: true, submit: ...
- 【C++ 实验六 继承与派生】
实验内容 1. 某计算机硬件系统,为了实现特定的功能,在某个子模块设计了 ABC 三款芯片用于 数字计算.各个芯片的计算功能如下: A 芯片:计算两位整数的加法(m+n).计算两位整数的减法(m-n) ...
- 变量类型-List
教程:一:列表的创建 List(列表) 是 Python 中使用最频繁的数据类型.列表中元素的类型可以不相同,数字,字符串甚至可以包含列表(所谓嵌套) (1)List写在方括号之间,元素用逗号隔 ...