【问题标题】:Are multiple variable assignments done by value or reference?多个变量赋值是按值还是按引用完成的?
【发布时间】:2011-09-09 13:42:56
【问题描述】:
$a = $b = 0;

在上面的代码中,$a$b是否都被赋值为0,还是$a只是引用$b

【问题讨论】:

    标签: php variables variable-assignment


    【解决方案1】:

    这取决于你分配什么。

    如果您正在分配一个值,那么该分配会将原始变量复制到新变量。

    示例一:

    $a = $b = 0;
    $b++; echo $a;
    

    上面的代码将返回0,因为它是按值赋值的。

    示例 2:

    $a = ($b = 4) + 5; // $a is equal to 9 now, and $b has been set to 4.
    

    在 PHP 中通常的按值赋值行为有一个例外,对象是在 PHP 5 中通过引用自动分配的。对象可以通过 clone 关键字显式复制。

    示例 3

    $a = $b = $c = new DOMdocument();
    $c->appendChild($c->createElement('html'));
    echo $a->saveHTML();
    

    上面的代码将打印<html></html>

    【讨论】:

      【解决方案2】:

      对于原始类型,这是一个副本。

      test.php

      $a = $b = 0;
      
      $b = 3; 
      
      var_dump($a);
      var_dump($b);
      

      输出

      int(0) 
      int(3)
      

      但对于对象,那是另一回事 (PHP 5)

      test.php

      class Obj
      { 
          public $_name;
      }
      
      $a = $b = new Obj();
      
      $b->_name = 'steve';
      
      var_dump($a);
      var_dump($b);
      

      输出

      object(Obj)#1 (1) { ["_name"]=> string(5) "steve" } 
      object(Obj)#1 (1) { ["_name"]=> string(5) "steve" }
      

      【讨论】:

      • 请注意,该示例具有误导性:更改对象的属性与更改引用对象的变量不同。因为变量从未改变,它当然是一样的。
      • 根据documentation,PHP 使用写时复制系统。这意味着原始类型(例如字符串或整数)在更改时确实在内存中创建。这就是为什么,与我们可能想象的相反,创建引用来优化小变量的性能可能不会带来预期的效果,因为 PHP 需要在之前创建它。但是,自 PHP5 起,对象默认通过引用传递。
      • 对象的引用分配可以使用clone更改为复制分配。例如:$a = clone $b = new Obj;
      • 在类变量声明级别会怎样?像这样private $_name = $address = "";
      【解决方案3】:

      我会推荐一个很好的阅读:http://terriswallow.com/weblog/2007/multiple-and-dynamic-variable-assignment-in-php/。在其中一个 cmets 中,您可以阅读:

      需要注意的是,如果你使用 一行上的多个赋值 分配一个对象,该对象是 通过引用分配。因此,如果 你改变对象的值 使用任一变量的属性, 两者的价值本质上都会发生变化。

      所以我个人建议你单独分配变量。

      记录在案:

      $a = $b = 4;
      var_dump($a, $b);
      $b = 5;
      var_dump($a, $b);
      

      产量:

      int(4)
      int(4)
      int(4)
      int(5)
      

      但是:

      class Tmp
          {
          public $foo;
      
          public function __construct()
              {
              $this->foo = 'bar';
              }
          }
      
      $a = $b = new Tmp();
      var_dump($a, $b);
      $a->foo = 'oth';
      var_dump($a, $b);
      

      产量:

      object(Tmp)#1 (1) {
        ["foo"]=>
        string(3) "bar"
      }
      object(Tmp)#1 (1) {
        ["foo"]=>
        string(3) "bar"
      }
      object(Tmp)#1 (1) {
        ["foo"]=>
        string(3) "oth"
      }
      object(Tmp)#1 (1) {
        ["foo"]=>
        string(3) "oth"
      }
      

      所以结论是没有对原语的引用,但是有对对象的引用。

      【讨论】:

      • 我们通过一些测试证明了这个错误。
      【解决方案4】:

      $a 和 $b 都被赋值为 0。如果你想让 $a 引用 $b,你可以用 & 号抢占它,例如:

      $a = & $b = 0;
      

      http://php.net/manual/en/language.oop5.basic.php

      【讨论】:

        【解决方案5】:

        它为它们分配了 0 的值

        【讨论】:

          【解决方案6】:

          将此代码视为:

          $a = ($b = 0);
          

          表达式$b = 0 不仅将0 分配给$b,而且还产生一个结果。该结果是分配的正确部分,或者只是分配给$b 的值。

          所以,$a 也被分配了 0

          【讨论】:

            【解决方案7】:

            你可以自己尝试一下

            $a = $b = 0;
            $a = 5;
            echo $b;
            

            $a = $b = 0;
            $b = 5;
            echo $a;
            

            (目前我真的不在乎:D)

            因此:不,它们都是值为0的自变量。

            【讨论】:

            • 在该示例中,您是否不必在第二行将 5 分配给 $b 以证明引用不存在?是的,你是对的。我认为在这里提出问题对于其他搜索也很好......
            • @Evil:不想多想,所以反过来也加了。两者都返回0,因此它必须在任何情况下都是真的:)
            猜你喜欢
            • 1970-01-01
            • 2010-09-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多