Передаются ли объекты PHP5 по ссылке?

Я не могу получить какую-либо последовательную информацию по этому вопросу. Различные источники, кажется, говорят разные вещи, и сам почтенный php.net (кажется) не заявляет об этом явно - хотя, должен признать, я только посмотрел.

В случаях, когда я передаю "тяжелые" объекты, мне нужно пройти по ссылке, но я не хочу продолжать печатать:

function foo(TypeName& $obj)

если я могу сойти с рук просто

function foo(TypeName $obj)

Так что же говорит стандарт?

8 ответов

Решение

Объекты передаются (и присваиваются) по ссылке. Нет необходимости использовать адрес оператора.

Конечно, то, что я напечатал, упрощено, но подойдет для ваших целей. В документации говорится:

Одним из ключевых моментов ООП PHP5, который часто упоминается, является то, что "объекты передаются по ссылкам по умолчанию". Это не совсем верно. Этот раздел исправляет эту общую мысль, используя некоторые примеры.

Ссылка PHP - это псевдоним, который позволяет двум разным переменным записывать одно и то же значение. Начиная с PHP5, переменная объекта больше не содержит сам объект в качестве значения. Он содержит только идентификатор объекта, который позволяет методам доступа к объекту найти фактический объект. Когда объект отправляется с помощью аргумента, возвращается или присваивается другой переменной, различные переменные не являются псевдонимами: они содержат копию идентификатора, который указывает на тот же объект.

Для более подробного объяснения (объясняет упрощение, а также идентификаторы) проверьте этот ответ.

Из руководства по PHP:

Вы можете передать переменную по ссылке на функцию, чтобы функция могла изменить переменную. Синтаксис выглядит следующим образом:

<?php
function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);
// $a is 6 here
?>

Примечание: в вызове функции нет знака ссылки - только в определениях функций. Одних только определений функций достаточно, чтобы правильно передать аргумент по ссылке. Начиная с PHP 5.3.0, вы получите предупреждение о том, что "передача по времени вызова не рекомендуется", когда вы используете & в foo(&$a);.

А из Что нового в PHP5:

В PHP 5 инфраструктура объектной модели была переписана для работы с дескрипторами объекта. Если вы явно не клонируете объект с помощью ключевого слова clone, вы никогда не будете создавать за сценой дубликаты ваших объектов. В PHP 5 нет необходимости передавать объекты по ссылке или присваивать их по ссылке

Поэтому единственный раз, когда вам нужно использовать function foo(&$var) синтаксис, если $var не может быть экземпляром класса.

Это кажется немного более точным, значение объекта передается по значению, но значение самого объекта является указателем. Это отличается от простой передачи ссылки.

На http://www.php.net/manual/en/language.oop5.references.php приведенный пример хорош. В первом наборе $a = NULL; не влияет на $ b, так как $ a был просто указателем. Во втором наборе $c = NULL; приводит к тому, что $ d также становится NULL, так как $ d является ссылкой на $ c.

<?php
class A {
    public $foo = 1;
}  

$a = new A;
$b = $a;
$a->foo = 2;
$a = NULL;
echo $b->foo."\n"; // 2

$c = new A;
$d = &$c;
$c->foo = 2;
$c = NULL;
echo $d->foo."\n"; // Notice:  Trying to get property of non-object...
?> 

Начиная с PHP 5, все объекты передаются и присваиваются по ссылке.

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

Просто пример, где полезно передавать "объекты" по ссылке:

class RefTest1
{
    public $foo;

    public function __construct(RefTest2 &$ref = null)
    {
        $this->foo =& $ref;
    }
}

class RefTest2
{
    public $foo;

    public function __construct(RefTest1 &$ref = null)
    {
        $this->foo =& $ref;
    }
}

class RefTest3
{
    public $foo;

    public function __construct(RefTest2 &$ref = null)
    {
        $this->foo =& $ref;
    }
}

class DoCrossRef
{
    public $refTest1;
    public $refTest2;

    public function __construct()
    {
        $this->refTest1 = new RefTest1($this->refTest2);
        $this->refTest2 = new RefTest2($this->refTest1);
    }

    public function changeReference()
    {
        $this->refTest1 = new RefTest3($this->refTest2);
    }
}

В конце RefTest1 содержит ссылку на RefTest2 и наоборот, также если RefTest2 объект не существовал в то время RefTest1 был создан.

После звонка DoCrossRef->changeReference(), RefTest2 объекты также содержит ссылку на новый RefTest3 объект.

Короткий ответ - да. Из объектов и ссылок:

Одним из ключевых моментов ООП PHP5, который часто упоминается, является то, что "объекты передаются по ссылкам по умолчанию". Это не совсем верно. Этот раздел исправляет эту общую мысль, используя некоторые примеры.

Ссылка PHP - это псевдоним, который позволяет двум разным переменным записывать одно и то же значение. Начиная с PHP5, переменная объекта больше не содержит сам объект в качестве значения. Он содержит только идентификатор объекта, который позволяет методам доступа к объекту найти фактический объект. Когда объект отправляется с помощью аргумента, возвращается или присваивается другой переменной, различные переменные не являются псевдонимами: они содержат копию идентификатора, который указывает на тот же объект.

Важно то, что в случае, если вас беспокоит, вы никогда не будете делать копию объекта, если не будете явно использовать ключевое слово clone в вызове функции. Будь то псевдоним или идентификатор, этот факт не изменится.

Да, начиная с PHP5, объекты передаются по ссылке. Нет необходимости делать это явно.

http://www.php.net/manual/en/migration5.oop.php

В PHP 5 появилась новая объектная модель. Обработка объектов в PHP была полностью переписана, что позволило повысить производительность и расширить возможности. В предыдущих версиях PHP объекты обрабатывались как примитивные типы (например, целые числа и строки). Недостаток этого метода состоял в том, что семантически весь объект копировался при присвоении переменной или передавался в качестве параметра методу. В новом подходе на объекты ссылаются по дескриптору, а не по значению (можно рассматривать дескриптор как идентификатор объекта).

Вот еще один пример, подтверждающий, что объекты передаются по ссылке.

<?php

// discussion: https://stackru.com/questions/2715026/are-php5-objects-passed-by-reference#_=_
class A {
    public $foo = 1;
}

class B {
    function inc($obj) {
        $obj->foo++;
    }
}

$objA = new A();
$objB = new B();
$objB->inc($objA);

echo "[" . $objA->foo . "]"; // Outputs [2]
Другие вопросы по тегам