值传递:将一个变量的值,复制一份,把新的这份交给另外一个变量保存,从而在内存中产生两个变量,对应两个不同的值,任何一个的修改都不会影响彼此。
$变量1 = 值; $变量2 = $变量1;
引用传值:变量实际保存的是数据对应的内存地址,如果将一个变量所保存的内存地址赋值给另外一个变量,存在两个变量共同指向同一块内存地址,一个变量的修改会导致另外一个变量的修改。 引用传递必须在被传递的变量之前使用地址符号:&
$变量1 = 值; $变量2 = &$变量1; // 取$变量1的地址
内存分析
内存都是分为以下几个部分:
- 栈区:是程序所能操作的理论上唯一的内存区域,内存很小,但是效率最高。
- 堆区:是唯一的内存地址连续的内存,内存很大,但是效率最低。
- 代码段:装载代码的内存,程序要运行,必须先将代码装载到代码段,然后在代码段里面逐行的运行程序代码。
- 数据段:是普通数据存储的内存,里面通常还分为两块区域: 全局区存放普通数据;静态区存储常量和静态数据。
在内存中,程序所能操作的只有栈区,数据段和堆区都是由栈区来操作
PHP代码的执行
PHP是一种高级语言(接近自然语言),所以不可能被计算机直接解析(计算机只能识别机器码(二进制))。
- 将所有的脚本(代码)加载到内存(代码段)
- 编译(词法分析、语法分析)
- 生成opcode:机器可以执行的代码(二进制)
- zendEngine(zend引擎)解析opcode,返回执行结果
PHP代码内存分析
- 将代码加载到代码段:编译
- 逐行的执行代码
- PHP将执行结束的结果返回
举个例子
// 定义变量 $f = 1; $s = $f; // 值传递 $t = &$f; // 引用传递 const PI = 3.14; // 修改变量 $s = 2; $t = 3; // 输出 echo $f,$s,$t;
1.加载源代码:编译(对代码进行优化)将代码加载到代码段
2.执行代码
2.1执行$f = 1;
①在栈区开辟空间存储$f
②在全局区开辟内存存储数据1
③将1
所在内存地址赋值给$f变量
2.2执行$s = $f;
①在栈区开辟空间存储$s
②取得$f
所存储地内存地址里面保存的数据1
③在全局区开辟一块新的内存地址保存值1
④将新的值1
的内存地址赋值给$t
2.3执行$t = &$f;
①在栈区开辟空间存储$t
②获取$f
所存储的内存地址
③将取出来的内存地址赋值给$t
2.4执行const PI = 3.14;
①在栈区开辟空间保存PI
②在静态区开辟内存存储3.14
③将3.14
的内存地址赋值给PI
2.5执行$s = 2;
①找到$s
变量所指向的内存地址
②修改原来的值为2
2.6执行$t = 3;
①找到$t
变量所指向的内存地址
②修改原来的值为3
2.7执行echo $f,$s,$t;
通过变量找到内存地址,取出里面的值并输出:3,2,3
3.脚本执行结束:释放所有的内存(栈区和代码段)
3.1代码段自动释放
3.2释放所有程序内存(栈区)
3.3操作系统回收内存:凡是没有被引用的全部回收