РНР5:: Удаление по ссылке не работает

camka

не самка
РНР5:: Удаление по ссылке не работает

Для примера рассматриваю простой двусвязный список, каждый элемент которого имеет ссылку на предществующий и последующий элемент.

PHP:
<?php
class uga
{
	public $parent = null;
	public $child = null;
	public $text;

	public function __construct($text)
	{
		$this->text = $text;
	}

	public function &add_child($text)
	{
		$this->child = new self($text);
		$this->child->parent = &$this;
		return $this->child;
	}

	public function delete()
	{
		$tmp = &$this;
		$tmp = null;
	}
}

$node		= new uga('root');
$first_child	= &$node->add_child('first_child');
$node = null;

echo '<pre>';
print_r($node);
echo "================\n";
print_r($first_child);
echo '</pre>';
?>
Использование нововведения пхп5, где по умолчанию объекты всегда передаются по ссылке, сразу отпало, поскольку при обнулении объекта, на который ссылаются другие объекты обнуляет лишь сам удаляемый объект, а все ссылки на него продолжают жить, как ни в чем не бывало.

Поэтому везде использую синтаксис присвоения по ссылке.

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

Я продолжаю грешить на неполноценность$this объкта внутри класса. Он все портит, поскольку является, насколько я знаю, некой временной сущностью.

Единственным решением пока нахожу передачу самого объекта по ссылке в функцию добавления потомка: т.е.

PHP:
	public static function &add_child($text, &$parent)
	{
		$parent->child = new self($text);
		$parent->child->parent = &$parent;
		return $this->child;
	}
Вопрос, можно ли это решить как-то более эллегантным способом.

спасибо
 

Screjet

Новичок
У тебя ошибка в использовании ссылок (независимо от версии).
Пока на переменную (будь то объект, или скаляр) существует хотя бы одня ссылка, после unset, переменная продолжает жизнь, т.к. связана с существующей ссылкой.

В твоем примере $first_child = есть ссылка, которая связана с объектом.

зы. В ПХП5 ненужно конкретно указывать передачу по ссылке для объектов. В любом случае передаются ссылки на объект. Оставили "&" чиста для обратной совместимости.
 

camka

не самка
Дело в том, что я не делаю unset, я непосредственно обнуляю переменную, и соответственно все ссылки на неё, присваивая ей значение null. Посмотрите эти два примера. В первом случае объекты присваиваются по жесткой ссылке, во втором - так как мне надо, для осуществления моей задачи.

PHP:
<?php
class uu{
}

$obj = new uu(1);

$ref1 = $obj;
$ref2 = $ref1;

$ref2 = null;

echo '<pre>';
var_dump ($obj, $ref1, $ref2);
echo '</pre>';

$ref1 = &$obj;
$ref2 = &$ref1;

$ref2 = null;

echo '=======<pre>';
var_dump ($obj, $ref1, $ref2);
echo '</pre>';
?>
 

Screjet

Новичок
PHP:
class uu{
}

$obj = new uu(1);
и два варианта ниже, по идее, для ПХП5 идентичные, но с совершенно разным поведением.

классич. для ПХП5
PHP:
$ref1 = $obj;
$ref2 = $ref1;
$ref2 = null;
и для ПХП4 (с обратной совместимостью для ПХП5)
PHP:
$ref1 = &$obj;
$ref2 = &$ref1;
$ref2 = null;
Причем неизвестно, какой из вариантов отрабатывает правильно :)

Есть смысл почитать последние изменения в зенд. Возможно на предмет этого там чтото написано.
 

_RVK_

Новичок
Screjet
Ихо не идентичные. Может я ошибаюсь, но $ref2 = $ref1; должен копировать объект, так как объект обычная переменная. Изменения насаются new которая возвращает ссылку на обект а не сам объект.
т.е.
$obj = new uu(1);
и
$obj = & new uu(1);

в PHP5 идентичны.

Поправте, если я не прав.
 

camka

не самка
Всё дело в том, что это на самом деле фича для ПХП5. Разный синтаксис предусмотрен для разного поведения, о чем, насколько я понял, гласит и всеми уважаемый мануал:

Example 19-3. Object Assignment

PHP:
<?php
$assigned  =  $instance;
$reference  =& $instance;

$instance->var = '$assigned will have this value';

$instance = null; // $instance and $reference become null

var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
The above example will output:
Код:
NULL
NULL
object(SimpleClass)#1 (1) {
   ["var"]=>
     string(30) "$assigned will have this value"
}
Однако, описания всего этого поведения я там не нашел.

Собственно, суть-то в том, что я как раз-таки использую ссылочную функциональность, а она не работает. Кто виноват и что делать? (с) ...
 

_RVK_

Новичок
Оказалось не бред....
PHP:
<?php
class a {
    function a() {
        $this->st='Class a';
    }
}

$a = &new a();
$b = $a;
$b = null;
print $a->st;

function foo($a) {
    $a->st= 'Changed in foo';
}

foo($a);
print $a->st;

phpinfo();

?>
$b явлется клоном а не ссылкой. Но вот в функцию передается действительно ссылка а не копия. те
PHP:
function foo($a) {
    ...
}
идентично
PHP:
function foo(&$a) {
    ...
}
-~{}~ 07.02.05 16:42:

camka
Из моего опыта выше ясно, что при присвоении '&' обязателен иначе объект копируется. Да и из твоего примера это тоже ясно.
 

camka

не самка
нашел занятное объяснение сему феномену на той же странице мануала в комментариях пострадавших. Кто-то даже постарался излить свое понимание в наглядном виде.

http://www.prism.gatech.edu/~gtg624r/Code_Explenation.gif

-~{}~ 07.02.05 15:46:

Автор оригинала: _RVK_
$a = &new a();
Подобный синтаксис является depricated для ПХП5. И что-то мне говорит о том, что ты это дело пробуешь для ПХП4, где дела обстоят проще. Проблема-то встает для ПХП5.
 

_RVK_

Новичок
Нет, я это пробую в PHP 5.0.0 иначе бы пример с функцией не прокатил бы.
Как я уже сказал что
$obj = new uu(1);
и
$obj = & new uu(1);
равнозначны. те в ПХП 5 изначально $obj является ссылкой а не переменной.
Но вопрос в другом. $a = $obj по прежнему копирует объект. Либо я чего то не понимаю....
 

camka

не самка
Автор оригинала: _RVK_
Нет, я это пробую в PHP 5.0.0 иначе бы пример с функцией не прокатил бы.
обнови версию. пхп5 уже давно вышла из беты.
Как я уже сказал что
...
равнозначны.
никто и не спорит. Именно поэтому-то и отменили такой синтаксис в 5-й версии.
те в ПХП 5 изначально $obj является ссылкой а не переменной.
почему ты считаешь, что ссылка - это не переменная. еще какая переменная.
Но вопрос в другом. $a = $obj по прежнему копирует объект. Либо я чего то не понимаю....
читай внимательно мануал и ссылки, что я привел выше.
 

_RVK_

Новичок
почему ты считаешь, что ссылка - это не переменная. еще какая переменная.
Не так выразился, но думаю ты меня понял.
читай внимательно мануал и ссылки, что я привел выше.
Спасибо, теперь я действительно понял.
 

Screjet

Новичок
camka,

Похоже в ПХП5 появилась разница понятий:
- жесткая ссылка
- ссылка на объект
:)

..как обычно придется адаптироваться (т.к. пхп5 уже продакшн)
 

camka

не самка
Автор оригинала: Screjet
camka,

Похоже в ПХП5 появилась разница понятий:
- жесткая ссылка
- ссылка на объект
:)
Это я пытался донести еще в первом посте. Проблема совсем в другом - я-то как раз использую эту фичу для своих целей, но она работает не так, как должна: опять же смотри мой первый пост. Сейчас попробую набрасать еще более тривиальный пример.

-~{}~ 07.02.05 17:40:

PHP:
<?php
class uu
{
	public $ref;

	public function set_me_as_ref(uu &$whom)
	{
		// seems like $this is not the object itself, but some kinda copy ... [?]
		$whom->ref = &$this;
	}
}

$obj1 = new uu();
$obj2 = new uu();

$obj2->set_me_as_ref($obj1);

$obj2 = null; // this won't unset $obj1->ref, but unsets only $obj2 object
// $obj1->ref = null; // this won't unset the $obj2 object, but unsets only $obj1->ref

echo '<pre>';
var_dump($obj1, $obj2);
?>
 

Screjet

Новичок
Смотри: в своем примере объекту ($obj1) ты передаешь ссылку на другой объект ($ob2), что предпологает использование объекта ($ob2) в будущем.

Если в твоем случае объект в будущем не пригодится, то передавай новый объект прям аргументом, типа:
PHP:
$obj2->set_me_as_ref( new uu() );
Если нужно взаимодействовать с этим объектом ($ob2), то обращайся к нему через объект-родитель, типа:
PHP:
$obj2->ref->set_me_as_ref();
Даже если понадобиться этот дочерной объект ($obj2), создай на него ссылку из ($obj1) и пользуйся. После уничтожения ($obj1) он не будет уничтожен, а после уничтожения ссылки на ($obj2), объект $obj1 и $obj2 будут уничтожены окончательно (сработают деструкторы).

В таком стиле и действуй.

зы. Пытайся обходить вожможные непонятки, а не искать их :)

(сорри за ошыпки, времени совсем мало)
 

camka

не самка
То есть этим ты хочешь сказать, что такое поведение ПХП преднамереное. И багрепорт тут ни к чему, а следует тупо приспосабливаться к неразумной логике работы движка. Жаль, а я еще питал надежды ....
 

Screjet

Новичок
Originally posted by camka
То есть этим ты хочешь сказать, что такое поведение ПХП преднамереное. И багрепорт тут ни к чему, а следует тупо приспосабливаться к неразумной логике работы движка. Жаль, а я еще питал надежды ....
Нет, причины поведения неясны, но разнообразие, в некотором смысле, это хорошо, когда есть разные варианты = больше выбор реализаций.

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

Логика движка = это правила, которые следует соблюдать, а насчет неразумности.. ну не назовешь же разработчиков ПХП неразумными :)

(сорри за философию и нравоучения)
 

camka

не самка
Не соглашусь.
Запостщу-ка я в буг-репорт, посмотрим, как они там это дело прокоментируют. Хотя я надеялся здесь получить конкретный ответ, стоит ли придумывать решение через Ж*?№у или все-таки обождать чутка.

-~{}~ 10.02.05 00:37:

Да... именно, как я и предполагал, дело оказалось в особом поведении $this, который, как оказалось и подтвердилось компетентными лицами, является не обычным объектом, и, как следствие, ведет себя несколько иначе, чем можно было бы подумать изначально. Жаль...
 
Сверху