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

Posted

技术标签:

【中文标题】PHP 中的 "=&" 和 "&=" 运算符是啥意思?【英文标题】:What do the "=&" and "&=" operators in PHP mean?PHP 中的 "=&" 和 "&=" 运算符是什么意思? 【发布时间】:2010-11-24 22:40:23 【问题描述】:

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

搜索 Google 没有帮助。

【问题讨论】:

=& 不是“组合运算符”。这是一篇解释为什么你永远不应该写=&的帖子:***.com/a/63914758/2943403 【参考方案1】:

$a &= $b$a = $a & $b 的缩写,它是 bitwise-and 运算符。

$a =& $b 将 $a 作为 reference 分配给 $b。

【讨论】:

我认为没有=& 运算符。它是=(赋值)和一元&(引用)运算符的组合。 也在 php.net 上:参见“参考说明”部分。 @hacker:为特殊字符使用通用名称通常效果很好,例如“与 php”。 php.net/manual/en/language.references.whatdo.php 更多关于引用的解释。 吹毛求疵:“$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。

用途和效果

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

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

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

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

foreach 循环:foreach ($a as &$b) 分配给$b 将覆盖$a 中的相应值。完成后取消设置 $b,否则会遇到奇怪的问题! 函数/方法参数:function foobar(&$a)foobar 内分配给$a 将更改调用者作为$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
)
*/
?>

&=

&amp;==&amp; 无关。它来自一组赋值操作。这里只是一些:

+= -= *= /=

看到这里的趋势了吗?

二元算术运算符通常有对应的赋值。假设@ 是一个算术运算符(它不是在写作时),这样$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';

非常有用。

&amp;= 属于这些赋值运算符,因为&amp; 代表bitwise arithmetic AND operation。 PHP 文档中还列出了其他一些(参见上述链接),所有这些对许多编程语言都是通用的。

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

【讨论】:

你的答案更好,因为这些例子可以帮助像我这样的新手。

以上是关于PHP 中的 "=&" 和 "&=" 运算符是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

使用 PHP 显示数据库中的图像 [重复]

PHP foreach 循环使用"&$val" 地址符“&”

PHP foreach 循环使用"&$val" 地址符“&”

PHP和编程中的用户输入验证和安全性/一般安全性

在php中处理数组

&和&&的区别