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

68 php operators

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

搜索Google无济于事.

moo*_*moo 92

$a &= $b是短期的$a = $a & $b,其是按位与运算符.

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

  • 很难谷歌特殊字符:) (45认同)
  • 我不认为有一个`=&`运算符.它是`=`(赋值)和一元`&`(引用)运算符的组合. (11认同)
  • 或者php.net:http://www.php.net/manual/en/language.operators.bitwise.php (9认同)
  • @hacker:使用特殊字符的通用名称通常很有效,例如"ampersand php". (3认同)
  • 剔除:“`$ a =&$ b`将$ a分配为对$ b的引用”是错误的,因为$ a并不指向$ b(反之亦然),但是两者都指向同一位置。细微但重要的区别。 (3认同)
  • @MichaelKrelin-hacker PHP 本身没有解引用运算符。`&` 是上下文相关的。你是对的,`=&` 不是一个单一的运算符;相反,当前面有“=”时,“&”是一个运算符,允许有空格。或者您可能会说“&”修改了“=”运算符。 (2认同)

Zen*_*xer 37

=

$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
Run Code Online (Sandbox Code Playgroud)

对象

#!/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
)
*/
?>
Run Code Online (Sandbox Code Playgroud)

&=

&=与...无关=&.它来自一组赋值操作.这里只是几个:

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

看到这里的趋势?

二元算术运算符通常具有赋值对应项.比方说@是一个算术运算符(它不是写的),使得$a @ $b通常产生一个号码时$a,并$b是数字.(想想:加法,乘法,除法等)你经常需要做这样的事情吗?

$a = $a @ $b;
Run Code Online (Sandbox Code Playgroud)

很经常.重复似乎没有必要$a吗?许多语言(包括PHP)通过赋值运算符数组来解决这个问题:

$a @= $b;
Run Code Online (Sandbox Code Playgroud)

更为简单,对于习惯于这种符号的程序员来说,或许更加简洁和描述一目了然.(我当然觉得它更容易阅读,因为我已经习惯了它.)所以要加倍变量:

$a *= 2;
Run Code Online (Sandbox Code Playgroud)

快速,简单,相对描述性.某些语言(包括PHP)将此功能扩展到算术以外的一两个额外操作.值得注意的是:

$a = $a . 'Appended text';
// Is the same as:
$a .= 'Appended text';
Run Code Online (Sandbox Code Playgroud)

很有用.

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

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

  • 你的答案更好,因为这些例子可以帮助像我这样的新手. (3认同)