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