Давайте возьмем этот код в качестве основы: (refcounting documentation)
$a = new ArrayObject();
$a['ID'] = 42;
$b = &$a['ID'];
$c = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
Это дает:
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
) и $ с is copy as a reference (since PHP5), так что $ с является отнесение $ а (это теперь тот же объект: 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
становится независимым ()и is_ref=0
), а также $a['ID']
и $c['ID']
НО, как $c
и $a
зависят, $a['ID']
и $c['ID']
принимают одинаковое значение 37.
Теперь, давайте рассмотрим базовый код, и мы делаем: $c['ID'] &= 0;
UPDATE: Неожиданно мы получаем:
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;
)
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
ArrayObject реализует ArrayAccess так:
Как сказано в комментарии и documented here:
прямая модификация является тот, который заменяет полностью значение размерности массива, как и в $ OBJ [6] = 7. Косвенная модификация, с другой стороны, только изменяет часть измерения или пытается присвоить размерность ссылкой на другую переменную, как в $ obj [6] [7] = 7 или $ var = & $ obj [ 6]. Приращения с ++ и декременты с помощью - также реализуются таким образом, что требуется косвенная модификация.
Возможный ответ:
"Комбинированный оператор (+ =, - =, & =, | =) можно было бы работал таким же образом (косвенные изменения.)":
refcount
и is_ref
не влияют, поэтому (в нашем случае) изменяются значения всех связанных переменных. ($c['ID']
=>$a['ID']
=>$b)
Да, я не думаю, что это задокументировано. В руководстве указано, что ++ и - выполнить косвенную модификацию и, таким образом, вызывать 'ArrayAccess :: offsetGet()', а не 'ArrayAccess :: offsetSet()'. Для согласованности я полагаю, что + =, - =, и двоюродные братья были реализованы таким же образом. – cleong
@cleong Я не могу найти его в документах. Не могли бы вы указать, где? – webmaster777