Подтвердить что ты не робот

Возможно ли разыменовать ссылку в PHP?

У меня есть массив, который я использую в качестве стека для хранения пути через дерево. Каждый элемент указывает на node в дереве, и я хочу вынуть последний элемент, а затем установить объект, на который ссылается этот элемент, на null.

В принципе:

$node = array_pop($path);
*$node = null;

предполагая, что PHP имеет оператор '*', как это делают языки C-ish. Прямо сейчас у меня есть уродливое решение начать с родительского node и вспомнить, какой дочерний я взял, а затем установил значение null как в:

if($goLeft) {
    $parent->left = null;
} else {
    $parent->right = null;
}

Я говорю, что это уродливо, потому что массив, содержащий этот путь, создается публичной функцией в моем древовидном классе. Я хотел бы показать возможность работать непосредственно с узлами в пути через дерево, не подвергая детализации реализации, которая обращается к идиосинкразии (функции?) В PHP. ATM Мне нужно включить логическое значение в возвращаемом значении ($ goLeft в этом случае), чтобы я мог обанкротить невозможность разыменовать ссылку.

Это второй раз, когда я столкнулся с этой проблемой, поэтому, если кто-нибудь знает способ, я могу сделать что-то похожее на первый блок кода, пожалуйста, поделитесь!

(РЕДАКТИРОВАТЬ)

После экспериментов со многими перестановками и и массивов выясняется, что основная проблема заключалась в том, что я неправильно истолковал причину ошибки, которую я получал.

Я пробовал

$a = ($x > $y) ? &$foo[$bar] : $blah;

и получил "синтаксическую ошибку, неожиданную" и ";". Я интерпретировал это как означающее, что проблема заключалась в использовании & -оператора на $foo[$bar]. На самом деле оказывается, что виновником является? -оператор, поскольку

if($x > $y) {
    $a = &$foo[$bar];
} else {
    $a = null;
}

работает отлично. Таким образом, я пошел на дикую охоту на гусей, пытаясь найти обходной путь для проблемы, которой не было. Пока я не нарушаю цепочку & s, PHP делает то, что я хочу, чтобы работать с объектом, на который ссылается переменная (а не сама переменная). Пример

$a1 = new SomeClass;
$a2 = &$a1;
$a3 = &$a2;
$a4 = &$a3;

$a4 = 42;    // This actually sets $a1 to 42
var_dump($a1); // Emits 42

Что меня перепутало, так это то, что я думал, что объекты все равно передаются по ссылке (это неправильно), поэтому я не думал, что это необходимо, и если выражение разрешено для объекта. Я имею в виду:

class A {
    public $b;
}

class B {}

$a = new A;
$a->b = new B; 

$c1 = $a->b; 
$c2 = &$a->b;

$c1 = 42; // Merely assigns 42 to $c1
$c2 = 42; // Assigns 42 to $a->b

Оказывается, эта точная проблема решается на http://www.php.net/manual/en/language.oop5.references.php. Хотелось бы, чтобы в первый раз я его прочитал!

4b9b3361

Ответ 1

Очень интересный вопрос! Возможно, я нашел обходное решение: если вы заполнили массив ссылками на объекты, с оператором &, вы можете уничтожить исходный объект, установив для этого значения массива значение NULL. Вы должны работать с массивом напрямую, вместо использования переменной, возвращаемой array_pop. После этого вы можете вывести массив, чтобы освободить эту позицию (которая затем будет содержать значение NULL).

Это то, что я имею в виду (на основе Rocket-кода):

$a=(object)'a';
$b=array(&$a);
$b[0] = NULL;
// array still contains an element
array_pop($b);
// now array is empty
var_dump($a); // NULL

http://codepad.org/3D7Lphde

Ответ 2

Мне хотелось бы запомнить, где я это прочитал, но PHP работает, поддерживая счетчик ссылок на данный объект. У вас есть некоторый объект (например, a Tree), который имеет ссылку на некоторые узлы. Когда вы используете array_pop, возвращается ссылка на объект node (т.е. Создается дополнительная ссылка), но исходная ссылка все еще существует. Когда вы unset выталкиваете ссылку, которая уничтожается, но исходный объект не уничтожается, потому что Tree все еще имеет эту ссылку. Единственный способ освободить память об этом объекте - иметь Tree уничтожить его лично (что, кажется, то, что вы делаете во втором блоке кода).

PHP, похоже, не имеет метода для принудительного удаления памяти или сбора мусора, поэтому, если вы не будете тщательно обрабатывать свои ссылки, вы застряли.

Это невозможно

P.S. Я все еще очень смущен тем, что вы пытаетесь сделать. Объяснение ракеты помогает, но что такое $path и как оно относится ко второму блоку?

Ответ 3

Просто не присваивайте возвращаемое значение array_pop().

php > $test = array(1, 2, 3);
php > $test2 = array(0 => &$test[0], 1 => &$test[1], 2 => &$test[2]);
php > array_pop($test2);
php > var_dump($test);
array(3) {
  [0]=>
  &int(1)
  [1]=>
  &int(2)
  [2]=>
  int(3)
}
php > var_dump($test2);
array(2) {
  [0]=>
  &int(1)
  [1]=>
  &int(2)
}

Ответ 4

$one = 1;
$two = 2;
$array = array(&$one, &$two);

// magic
end($array);
$array[key($array)] = NULL;

var_dump($two);
// NULL

Ссылка в php позволяет вам изменять объект.