首页 > 技术文章 > 题(2)

gyfluck 2020-11-03 10:46 原文

1、请写出下列的结果:

$a = 123;
$b = &$a;

var_dump($b);//123

$a = 456;
var_dump($b);//456


unset($a);
var_dump($b);//456

关于变量引用:

  (1)普通的变量赋值。

    执行COW机制,即copy On Write。

    当一个变量等于另一个变量时,并没有增加一块新空间的开销,而是两个变量指向同一个内存空间;  

    当其中一个变量重写时(无论值是否改变),会为这个重写的变量增加一块单独的内存空间。 

    示例:

$a = range(0,1000);
var_dump(memory_get_usage());//打印内存,878408

$b = $a;
var_dump(memory_get_usage());//打印内存,878408,发现没变化或变化很小

$a = range(0,1000);//$a重新赋值,虽然值没有变化
var_dump(memory_get_usage());//打印内存,915328,发现变化很大,因为$a重新使用了一块空间。

  (2)当进行引用赋值。

    变量永远指向同一个内存空间,所以内存不会变化或变化很小。

$a = range(0,1000);
var_dump(memory_get_usage());//打印内存,878408

$b = &$a;
var_dump(memory_get_usage());//打印内存,878432,发现变化很小

$a = range(0,1000);//$a重新赋值,虽然值没有变化
var_dump(memory_get_usage());//打印内存,878432,发现没变化或变化很小。

  扩展:可以打印zval结构体来查看变量的底层的存储,zval就是变量容器,管理变量内容。安装xdebug扩展。

$a = range(1,3);
$b = &$a; xdebug_debug_zval(
'a');

  recount=1;说明只有一个变量指向这个内存空间。

  is_ref=1;说明有一个引用


2、关于对象的赋值:

class user{
    public $name = '';

    public function setName($newName = ''){
        $this->name = $newName;
    }

    public function getName(){
        return $this->name;
    }
}

$a = new user();
$b = $a;
$c = clone $a;
$a->setName('123');
var_dump($b->getName());//string '123'
var_dump($c->getName());//string ''

正确结果是:123;说明对象之间的赋值,本身就是引用传值,指向同一个内存空间,如果不想使用同一个对象,就需要使用clone关键字复制一个对象。


 

3、请分析下面程序,写出结果:

$data = array('a','b','c');
foreach ($data as $k => $v) {
    $v = &$data[$k];
}
问:
(1)程序运行时,每一次循环结束后变量$data的值是什么,请解释。
(2)程序执行完成后,变量$data的值是什么?请解释。

分析:
第一轮循环:
    $k=0;
    $v='a';
    $v = &$data[0];//$v和$data[0]指向同一个空间

    所以第一轮结果:
    $data = array('a','b','c');

第二轮循环:
    $k=1;
    $v='b';//因为第一轮$v和$data[0]指向同一个空间,所以$v变化,$data[0]就变化。
    $v = &$data[1];//$v和$data[1]又指向同一个空间

    所以第二轮结果:
    $data = array('b','b','c');    


第三轮循环:
    $k=2;
    $v='c';//因为第二轮$v和$data[1]指向同一个空间,所以$v变化,$data[1]就变化。
    $v = &$data[2];//$v和$data[2]又指向同一个空间

    所以第二轮结果:
    $data = array('b','c','c');    

最终结果:
var_dump($data);//array('b','c','c');

 

推荐阅读