Php 玩弄参考资料

Php 玩弄参考资料,php,reference,binary-operators,Php,Reference,Binary Operators,我明白为什么了 $a = new ArrayObject(); $a['ID'] = 42; $b = &$a['ID']; $c = $a; $c['ID'] = 37; echo $a['ID']."\n"; echo $b."\n"; echo $c['ID']."\n"; 产出37、42、37 当 产出37、37、37 在这两种情况下,$b都是对$a['ID']的引用,$c是指向与$a相同对象的指针 当$b更改$a['ID']和$c['ID']更改时,因为分配$b会更改$a['

我明白为什么了

$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
$c['ID'] = 37;
echo $a['ID']."\n";
echo $b."\n";
echo $c['ID']."\n";
产出37、42、37

产出37、37、37

在这两种情况下,
$b
都是对
$a['ID']
的引用,
$c
是指向与
$a
相同对象的指针

$b
更改
$a['ID']
$c['ID']
更改时,因为分配
$b
会更改
$a['ID']
引用的值

$c['ID']
更改时,一个新的int被分配给
$a['ID']
$b
不再引用
$a['ID']

但这让我很痒

$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
$c['ID'] &= 0;
$c['ID'] |= 37;
echo $a['ID']."\n";
echo $b."\n";
echo $c['ID']."\n";
(产出37、37、37)

这是定义的行为吗?
我在文档中没有看到任何关于这方面的内容…

让我们以这段代码为基础:()

这使得:

a:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
  public 'ID' => (refcount=2, is_ref=1),int 42
b:
(refcount=2, is_ref=1),int 42
c:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
  public 'ID' => (refcount=2, is_ref=1),int 42
正如你所说:
$a
是一个对象,
$b
$a['ID']
的引用(
$a['ID']
$b
refcount=2,is_ref=1
) 和$c,因此$c是$a的引用(现在是同一个对象:
refcount=2,is_ref=0


如果我们这样做:
$c['ID']=37

我们得到:

a:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
  public 'ID' => (refcount=1, is_ref=0),int 37
b:
(refcount=1, is_ref=0),int 42
c:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
  public 'ID' => (refcount=1, is_ref=0),int 37
$c['ID']
被分配了一个新的
int
so=>

$b
变得独立(
refcount=1
is_ref=0
),以及
$a['ID']
$c['ID']

但是由于
$c
$a
是依赖的,
$a['ID']
$c['ID']
采用相同的值


现在,让我们看一下基本代码:
$c['ID']&=0

a:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
  public 'ID' => (refcount=1, is_ref=0),int 0
b:
(refcount=1, is_ref=0),int 42
c:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
  public 'ID' => (refcount=1, is_ref=0),int 0
更新: 出乎意料的是,我们得到:

a:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
  public 'ID' => (refcount=2, is_ref=1),int 0
b:
(refcount=2, is_ref=1),int 0
c:
(refcount=2, is_ref=0),
object(ArrayObject)[1]
  public 'ID' => (refcount=2, is_ref=1),int 0
而不是:(如果:
$c['ID']=$c['ID']&0;

ArrayObject实现ArrayAccess,因此:

如评论和评论中所述:

直接修改是完全替换数组维度值的修改,如$obj[6]=7。另一方面,间接修改仅更改维度的一部分,或尝试通过引用另一个变量来分配维度,如$obj[6][7]=7或$var=&$obj[6]。用++递增,用-,递减也以需要间接修改的方式实现

一个可能的答案是:

“组合运算符(+=,-=,&=,|=)可以以相同的方式工作(间接修改)。”

refcount
is_ref
不受影响,因此(在本例中)所有 修改相关变量。(
$c['ID']
=>
$a['ID']
=>
$b)

它或多或少是有定义的(但有时是没有记录的)行为;主要是因为
$a
不是
数组
,而是
数组对象

让我们先看一下您的第三个代码片段:

$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
$c['ID'] &= 0;
最后一项作业翻译为:

$tmp = &$c->offsetGet('ID');
$tmp &= 0; // or: $tmp = $tmp & 0;
此处的外卖点仅被调用,它返回对
$c['ID']
的引用,如中所述。由于未调用
offsetSet()
,因此
$b的值也会更改

顺便说一句,递增(++)和递减运算符(--)的工作方式类似,不调用
offsetSet()

差异

这与第一个示例不同:

$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
$c['ID'] = 37;
最后一条语句具有以下等效项:

$c->offsetSet('ID', 37);
在将新值分配给
$c['ID']
之前,先前的值实际上是
unset()
;这就是为什么
$b
是唯一仍然保持
42
不变的变量

当您使用对象而不是数字时,可以看到这种行为的证据:

class MyLoggerObj
{
        public function __destruct()
        {
                echo "Destruct of " . __CLASS__ . "\n";
        }
}

$a = new ArrayObject();
$a['ID'] = new MyLoggerObj();
$a['ID'] = 37;

echo $a['ID']."\n";
:

如您所见,析构函数是在
MyLoggerObj
上调用的;这是因为在这种情况下,不再有变量保留该值

奖金


如果您试图通过扩展
ArrayObject
来确定何时调用
offsetGet()
offsetSet()
,您将失望地发现无法正确模拟
mixed&offsetGet($key)。事实上,这样做会改变
ArrayObject
的行为,以至于无法证明此类的行为。

是的,我认为没有文档记录。本手册仅说明++和--执行间接修改,从而触发
ArrayAccess::offsetGet()
,而不是
ArrayAccess::offsetSet()
。为了保持一致性,我猜+=、-=、和cousins是以相同的方式实现的。@cleong我似乎在文档中找不到它。你能指出在哪里吗?和例1相比,你看不出这是多么出乎意料吗?仍然不确信:P,为什么在例1中b没有得到更新?根据偏移集的预期行为,它会更改引用(间接修改),但b也应该是37。我只能猜测其他语义在这里起作用,但一旦我进入计算机,我会对这方面给予一些注意。这将使Ex.3产生37,42,37(因为引用$c['id']按您的标准设置为未设置,然后设置为0)。
$c->offsetSet('ID', 37);
class MyLoggerObj
{
        public function __destruct()
        {
                echo "Destruct of " . __CLASS__ . "\n";
        }
}

$a = new ArrayObject();
$a['ID'] = new MyLoggerObj();
$a['ID'] = 37;

echo $a['ID']."\n";
Destruct of MyLoggerObj
37