【PHP面试题】什么是 引用变量?在PHP当中,用什么符号定义引用变量?


一. PHP引用变量考察点

1. PHP的引用变量的概念及定义方式

概念

在PHP中,引用意味着用不同的名字访问同一个变量内容。

定义方式

使用 & 符号

2. 延伸:PHP引用变量的原理

1)赋值

将一个变量的值赋值给另一个变量,其中一个变量的值进行改变,会重新进行拷贝,此时会再开辟一个新的内存空间。

// 1. 定义一个变量
$a = range(0, 1000); // 在内存中开辟一片空间,存储变量a
var_dump(memory_get_usage()); // int(406512)

// 2. 定义变量 b,将 a变量的值赋值给 b
$b = $a; // 将变量b 指向 变量a开辟的空间中
var_dump(memory_get_usage()); // int(406568)

// 3. 对 a进行修改
$a = range(0, 1000);
var_dump(memory_get_usage()); // int(406568)

原理:使用了 COW(Copy On Write)机制 : 对 $a$b 其中一个进行改变,内存空间才会发生改变。

  • 在内存中开辟一片空间存储变量a;
  • 将变量b 指向 变量a的内存空间中;
  • 对变量a进行修改(对a进行写操作),此时会再开辟一片内存空间存储a和a和a和b(原来的a和a和a和b被改变)

2)引用

两个变量无论何时都共用一个内存空间(对其中一个的值进行更改的时候,不会开辟新的内存空间)

// 1. 定义一个变量
$a = range(0, 1000);
var_dump(memory_get_usage());

// 2. 定义变量b, 将a变量的值赋值给b
$b = &$a;
var_dump(memory_get_usage());

// 3. 对a进行修改
$a = range(0, 1000);
var_dump(memory_get_usage());

原理:

  • 定义一个变量$a(开辟一个内存空间存储变量$a);
  • 定义变量$b,将$b,将$b,将$a的地址给了$b,此时$b,此时$b,此时$b$a指向同一个内存空间,且永远指向该内存空间(不会再重新拷贝,改掉的只是该内存空间的值);
  • 对a进行修改(不会再开辟内存空间),此时a和a和a和b的值,都是修改后的值;

3)unset 只会取消引用,不会销毁内存空间

$a = 1; // 开辟一个内存空间存储变量a,并赋值为1
$b = &$a; // 将$a的引用赋值给$b,此时$a和$b指向同一个内存空间(永久指向)
unset($b); // 此时取消的是$a和$b的引用,不会取消内存空间
echo $a; // 1

4) 对象本身就是引用传递,因此,在修改的时候,不会再重新开辟内存空间

class Person
{
    public $name = 'zhangsan';
}

$p1 = new Person; // 开辟一个内存空间存储$p1
$p2 = $p1; // 将$p1和$p2存入同一个内存空间(内存空间会变大)
$p2->name = 'lisi'; // $p1,$p2都为lisi,因为指向的是同一个内存空间

二. 真题

写出如下程序的输出结果:

$data = ['a', 'b', 'c'];

foreach ($data as $key => $val) { 
    $val = &$data[$key]; 
}

程序运行时,每一次循环结束后变量 $data 的值时什么?请解释

程序执行完成后,变量 $data 的值时什么?请解释

1)答案:

// 第一次循环
$data = ['a', 'b', 'c'];
// 第二次循环
$data = ['b', 'b', 'c'];
// 第三次循环
$data = ['b', 'c', 'c'];

// 程序执行完成后,变量 $data的值
$data = ['b', 'b', 'c'];

2)解析:

1foreach ($data as $key => $val)
    会将$data第一个元素的键名赋值给$key,将$data的第一个元素的值赋值给$val($k=0; $v=a;)
2) $val = &$data[$key]; 
    $v = &$data[0];(即$v拿了$data[0]的地址)
    $v = &$data[0] = a(此时$data[0]$v都指向 a内存空间)

以上步骤即为:
1)第一次循环:
    $k = 0;
    $v = a;
    $v = &$data[0];
    ($v = &$data[0] = a,$v$data[0] 都指向 a内存空间) // 结果:$data = ['a','b','c'];
2)第二次循环:
    $k = 1;
    $v = b;
    $data[0] = b;
    $v = &$data[1];
    ($v = &$data[1] = b, $v$data[1] 都指向 b内存空间) // 结果:$data = ['b','b','c'];
3)第三次循环:    
    $k = 2;
    $v = c;
    $data[1] = $c;
    $v = &$data[2];
    ($v = &$data[2] = c, $v$data[1] 都指向 c内存空间) // 结果:$data = ['b','c','c'];

3)代码测试:

$data = ['a', 'b', 'c'];

foreach ($data as $k => $v) {
    $v = &$data[$k];
    var_dump($data);
}
var_dump($data);

运行结果:

// 第一次循环后, $data 的值
array(3) {
  [0] =>
  string(1) "a"
  [1] =>
  string(1) "b"
  [2] =>
  string(1) "c"
}
// 第二次循环后, $data 的值
array(3) {
  [0] =>
  string(1) "b"
  [1] =>
  string(1) "b"
  [2] =>
  string(1) "c"
}
// 第三次循环后, $data 的值
array(3) {
  [0] =>
  string(1) "b"
  [1] =>
  string(1) "c"
  [2] =>
  string(1) "c"
}
// 程序执行完后, $data 的值
array(3) {
  [0] =>
  string(1) "b"
  [1] =>
  string(1) "c"
  [2] =>
  string(1) "c"
}

文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
 上一篇
【PHP面试题】PHP的字符串的定义方式及各自区别(单引号,双引号,heredoc,newdoc)? 【PHP面试题】PHP的字符串的定义方式及各自区别(单引号,双引号,heredoc,newdoc)?
一、定义方式 单引号/ 双引号 / heredoc 和 newdoc;(三种) 1、 单引号// 单引号定义变量 $str = 'a b c d e f $a g'; // 此时$a会被原样输出 2、 双引号// 此处可以把 '{$a}'
2020-07-05
下一篇 
搭建 Hexo 博客 搭建 Hexo 博客
来源知乎原文 安装 Node.js首先下载稳定版Node.js,我这里给的是64位的。 安装选项全部默认,一路点击Next。 最后安装好之后,按Win+R打开命令提示符,输入node -v和npm -v,如果出现版本号,那么就安装成功了。
2020-03-14
  目录