PHP中的“ =&”和“&=”运算符是什么意思?


Answers:


93

$a &= $b的缩写$a = $a & $b,是按位与运算符。

$a =& $b分配$ a作为对$ b的引用


11
我认为没有=&操作员。它是=(赋值)运算&符和一元(引用)运算符的组合。
Michael Krelin-黑客

也在php.net上:请参见“参考资料解释”部分。
GZipp

3
@hacker:对特殊字符使用通用名称通常效果很好,例如“&s php”。
GZipp


3
细说:“$a =& $b将$ a分配为对$ b的引用”是错误的,因为$ a并不指向$ b(反之亦然),但是两者都指向同一位置。细微但重要的区别。
尔根·塞伦(JürgenThelen)

39

=&

$a =& $b变成$a的别名$b。如果的值或参考值$a发生更改,则的值或参考值$b将相应更改。

对于对象,这不同于“都指向相同的位置”:我可以做$c = $d = new AnObject(),并且两个变量都指向相同的位置。但是,更改一个点不会更改其他点。也就是说,$c = null不会$d = null。在的情况下$a =& $b,然而,$a = null将使$b = null

注意:正式而言,别名实际上称为引用。官方术语有点用词不当,而且肯定是模棱两可的,所以我选择改用“别名”一词。有关文档,请参见php.net

用途和效果

对于标量值,=&有点像将值包装在对象中,这样您就可以在多个变量之间通用地更改值。对于通常由引用(对象)传递的类型,=&提供对引用的引用。

我在使用=&关联数组时倾向于使用。$foo['bar']['foobar']我可以创建一个别名:,而不是重写几次$foobar =& $foo['bar']['foobar']。如果索引尚不存在,这些甚至可以工作。如果$foo['bar']['foobar']不存在,isset($foobar)则为假。它比使用普通的旧变量更好,因为我可以在测试键的存在之前创建别名而不会触发错误。

完成后,请务必取消设置(unset($foobar))别名。否则,如果以后再使用变量名,最终将覆盖别名指向的内容。

您也可以通过其他方式使用别名-它们不仅限于分配。他们与:

  • foreach循环:foreach ($a as &$b)分配给$b会覆盖中的相应值$a。完成后取消设置$b,否则会遇到奇怪的问题!
  • 函数/方法参数:function foobar(&$a)$a内部分配foobar将更改调用方以形式传递的任何变量$a
  • 函数/方法返回值:function &foobar() 无论返回什么,调用方都可以修改;这对于传递别名很有用。这也很容易滥用。
  • 数组:对的$a = array(&$b) 任何更改$a[0]现在都会影响$b,包括分配。
  • call_user_func_array:call_user_func('foobar', array(&$a)) 假设foobar有一个别名参数,foobar现在可以进行修改$a。这使您可以使用使用别名参数调用函数/方法call_user_func_array

例子

标量

$original = 1;
$copy = $original;
$reference =& $original;
// All three variables == 1.

$reference = 2;
// $original == 2, $reference == 2, $copy == 1

$original = 3;
// $original == 3, $reference == 3, $copy == 1

$copy = 4;
// $original == 3, $reference == 3, $copy == 4

对象

#!/usr/bin/env php
<?php
class Object
{
        private $properties;

        public function __construct(array $properties = array())
        {
                $this->properties = $properties;
        }

        public function __isset($key)
        {
                return isset($this->properties[$key]);
        }

        public function __unset($key)
        {
                unset($this->properties[$key]);
        }

        public function __get($key)
        {
                return isset($this->$key) ? $this->properties[$key] : null;
        }

        public function __set($key, $value)
        {
                $this->properties[$key] = $value;
        }

        public function __toString()
        {
                return print_r($this->properties, true);
        }
}

function print_vars()
{
        global $original, $ref, $refref;

        echo
                '$original: ', $original,
                '$ref: ', $ref,
                '$refref: ', $refref,
                PHP_EOL;
}

$original = new Object(array('a' => 1, 'b' => 2, 'c' => 3));
$ref = $original;
$refref =& $original;
print_vars();
/*
$original: Array
(
    [a] => 1
    [b] => 2
    [c] => 3
)
$ref: Array
(
    [a] => 1
    [b] => 2
    [c] => 3
)
$refref: Array
(
    [a] => 1
    [b] => 2
    [c] => 3
)
*/

$original->a = 'duck';
$ref->b = 'moose';
$refref->c = 'cow';
print_vars();
/*
$original: Array
(
    [a] => duck
    [b] => moose
    [c] => cow
)
$ref: Array
(
    [a] => duck
    [b] => moose
    [c] => cow
)
$refref: Array
(
    [a] => duck
    [b] => moose
    [c] => cow
)
*/

// This carries over to $refref, but not $ref.
$original = new Object(array('x' => 1, 'y' => 2, 'z' => 3));
print_vars();
/*
$original: Array
(
    [x] => 1
    [y] => 2
    [z] => 3
)
$ref: Array
(
    [a] => duck
    [b] => moose
    [c] => cow
)
$refref: Array
(
    [x] => 1
    [y] => 2
    [z] => 3
)
 */

// This does *not* carry over to $original or $ref.
$ref = new Object(array('o' => 42, 'm' => 123, 'n' => 1337));
print_vars();
/*
$original: Array
(
    [x] => 1
    [y] => 2
    [z] => 3
)
$ref: Array
(
    [o] => 42
    [m] => 123
    [n] => 1337
)
$refref: Array
(
    [x] => 1
    [y] => 2
    [z] => 3
)
*/

// This *does* carry over to $original, but not $ref.
$refref = new Object(array('alpha' => 10, 'beta' => 20, 'gamma' => 30));
print_vars();
/*
$original: Array
(
    [alpha] => 10
    [beta] => 20
    [gamma] => 30
)
$ref: Array
(
    [o] => 42
    [m] => 123
    [n] => 1337
)
$refref: Array
(
    [alpha] => 10
    [beta] => 20
    [gamma] => 30
)
*/
?>

&=

&=与无关=&。它来自一组分配操作。这里只是几个:

  • +=
  • -=
  • *=
  • /=

在这里看到趋势吗?

二进制算术运算符通常具有赋值对象。假设@是一个算术运算符(截至撰写时),这样$a @ $b通常会在$a$b是数字时产生数字。(认为​​:加法,乘法,除法等),您需要多久执行一次这样的事情?

$a = $a @ $b;

很经常。似乎没有必要重复$a吗?包括PHP在内的许多语言都通过一系列赋值运算符来解决此问题:

$a @= $b;

对于习惯了这种表示法的程序员而言,它要简单得多,而且乍一看可能更简洁,更具描述性。(因为我已经习惯了,所以我当然更容易阅读。)因此,将变量加倍:

$a *= 2;

快速,简单且具有描述性。某些语言(包括PHP)将此功能扩展到了算术之外,只需要执行一两个额外的操作即可。值得注意的是:

$a = $a . 'Appended text';
// Is the same as:
$a .= 'Appended text';

很有用。

&=落在这些赋值运算符之内,因为它&表示按位算术AND运算。PHP文档中还列出了其他一些内容(请参见前面的链接),这些都是许多编程语言所共有的。

这意味着$a &= $b与相同$a = $a & $b


3
最好的答案是您,因为这些示例可以帮助像我这样的新手。
Kim Stacks 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.