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

2022-08-30 08:29:57

PHP 中的 “=&” / “&=” 运算符是什么意思?我在哪里可以阅读有关它们的信息?

搜索谷歌没有帮助。


答案 1

$a &= $b按位和运算符的缩写。$a = $a & $b

$a =& $b将$a指定为对$b的引用


答案 2

=&

$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
  • 函数/方法参数:赋值到 within 将更改调用方作为 传递的任何变量。function foobar(&$a)$afoobar$a
  • 函数/方法返回值:返回的任何内容都可以由调用方修改;这对于传递别名很有用。它也很容易被滥用。function &foobar()
  • 数组:任何 更改现在都会影响 ,包括赋值。$a = array(&$b)$a[0]$b
  • call_user_func_array:假设采用单个别名参数,现在可以修改.这允许您使用 调用具有别名参数的函数/方法。call_user_func('foobar', array(&$a))foobarfoobar$acall_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;

经常。是不是有点没有必要重复?许多语言,包括PHP,都通过一系列赋值运算符来解决这个问题:$a

$a @= $b;

更简单,对于习惯于这种符号的程序员来说,也许一目了然地更简洁和描述性。(我当然发现它更容易阅读,因为我已经习惯了它。所以要将变量加倍:

$a *= 2;

快速,简单,相对描述性。一些语言,包括PHP,将此功能扩展到算术之外,以进行一两个额外的操作。特别是:

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

非常有用。

&=属于这些赋值运算符,因为表示按位算术 AND 运算。PHP文档中还列出了其他一些(参见上述链接),所有这些语言都是许多编程语言所共有的。&

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


推荐