search

Home  >  Q&A  >  body text

PHP unset函数好奇怪

unset传递的值是一个对象或者值的复制(比如传递数组,传递的是一个新的复制,而不是引用),结果原对象却被销毁了。好奇怪。
大神快来解答这个问题。以前一直用unset,今天突然想到了这个问题。
比如:


<?php $a='hello'; $b=true; unset($b); unset($a); echo $b; echo $a; ?>

这时就会报出Undefined variable的错误
正如舞林所说,这种销毁变量的方式有可能是将引用计数减一。
但是这样做:

<?php
$a='hello';
$b=&$a;
unset($a);
echo $a;

?>

这个时候,$a依然被销毁。报出Undefined variable的错误的错误。
如果unsetb,来看看结果:

<?php


$a='hello';
$b=&$a;
unset($b);
echo $a;

?>

只是销毁了$b,$b虽然是$a的引用,但是$a没有被销毁。打印出hello
所以unset的机制并没有那么简单。。

PHP中文网PHP中文网2903 days ago663

reply all(8)I'll reply

  • 巴扎黑

    巴扎黑2017-04-10 14:58:07

    第一段代码 a和b是两块不同的内存 所以unset掉两者 根本没影响
    第二段代码 b引用a 使得对应的zval ref_count+1 is_ref +1 此时不管unset掉a或者b 只是断了一根引用对另外的那个值没影响 还是指向的那块区域

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-10 14:58:07

    变量引用次数-1,只要有对该内存块的引用,该内存块就不会被销毁

    update:
    昨天写答案提交发现服务器在调皮的维护,以为没发出去呢...
    TIPI有写具体的内容:
    http://www.php-internals.com/book/?p=chapt03/03-01-00-variables-structure
    //变量结构体

    http://www.php-internals.com/book/?p=chapt03/03-06-01-var-define-and-init
    //变量的赋值和销毁,这里详细讲解了引用计数

    reply
    0
  • 天蓬老师

    天蓬老师2017-04-10 14:58:07

    我觉得你说得好像不成立。。

    $o = new stdClass();
    $o->var = 123;
    $new_o = $o; //等于$new_o = & $o;
    unset($new_o);
    var_dump($o);
    

    对象赋值本身就是引用赋值,但是unset 引用的变量 只是把引用给销毁了,并不会销毁原变量

    我的理解是这个样子

    reply
    0
  • 怪我咯

    怪我咯2017-04-10 14:58:07

    ...你 确定?

    ------------update-------------
    把评论里的拿上来
    unset只是断开了变量 名和值 之间的绑定

    引用:
    "该函数只有在变量值所占空间超过256字节长的时候才会释放内存"
    &&
    "有当指向该值的所有变量(比如有引用变量指向该值)都被销毁后,地址才会被释放"

    reply
    0
  • ringa_lee

    ringa_lee2017-04-10 14:58:07

    unset($a)无论你$a是怎么得到的(直接赋值$a=true、传值$a=$b、传址$a=&$b),以及对$a进行过什么操作(传值给别的变量$b=$a或传址$b=&$a),它都会断掉$a的引用,并把$a抹成null。
    至于被赋值的那个对象是不受影响的,引用计数自己会处理好。

    reply
    0
  • 阿神

    阿神2017-04-10 14:58:07

    同意楼上几位的回答,如果LZ的问题依然存在,不妨贴出你的代码可以更好的说明情况。

    不过我想通过以下代码给LZ提个醒:

    $foo = true;
    $bar = &$foo;
    unset($foo);
    var_dump($bar);  // 结果是true,而不是null
    

    另外反过来一样

    $foo = true;
    $bar = &$foo;
    unset($bar);
    var_dump($foo);  // 结果依然是true,而不是null
    

    可以看出:即时向unset传递一个变量的引用,也不会把该变量销毁
    所以我不太能理解LZ的问题是怎么一回事……

    reply
    0
  • PHP中文网

    PHP中文网2017-04-10 14:58:07

    这段代码是我从别处搜索来的,我认为应该能够解决你的疑问!
    如果在函数中 unset() 一个通过引用传递的变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。

      <?php
        function foo(&$bar) {
         unset($bar);
         $bar = "blah";
        }
    
    $bar = 'something';
    echo "$bar ";
    
    foo($bar);
    echo "$bar ";
    ?> 
    

    上边的例子将输出:

    something
    something

    reply
    0
  • 大家讲道理

    大家讲道理2017-04-10 14:58:07

    楼主第二个测试,可以输出$b 试试,一样没有被销毁

    参考这个
    http://php.net/manual/zh/features.gc.refcounting-basics.php

    reply
    0
  • Cancelreply