Я знаю, что это описано в php docs, но я смутился с этой проблемой.
Из документов php:
$instance = new SimpleClass(); $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); ?>
Вышеприведенный пример выводит:
NULL NULL object(SimpleClass)#1 (1) { ["var"]=> string(30) "$assigned will have this value" }
ОК, поэтому я вижу, что $assigned
исходный объект ( $instance
), которому присваивается значение null
, поэтому явно $assigned
не является ссылкой, а копией экземпляра $.
Так в чем разница между
$assigned = $instance
а также
$assigned = clone $instance
Объекты – абстрактные данные в памяти. Переменная всегда содержит ссылку на эти данные в памяти. Представьте себе, что $foo = new Bar
создает экземпляр объекта Bar
где-то в памяти, присваивает ему некоторый id #42
, а $foo
теперь содержит этот #42
качестве ссылки на этот объект. Присвоение этой ссылки другим переменным по ссылке или обычно работает так же, как и с любыми другими значениями. Многие переменные могут содержать копию, если эта ссылка, но все указывают на один и тот же объект.
clone
явно создает копию самого объекта, а не только ссылку, указывающую на объект.
$foo = new Bar; // $foo holds a reference to an instance of Bar $bar = $foo; // $bar holds a copy of the reference to the instance of Bar $baz =& $foo; // $baz references the same reference to the instance of Bar as $foo
Просто не путайте «ссылку», как в =&
с «ссылкой», как в идентификаторе объекта .
$blarg = clone $foo; // the instance of Bar that $foo referenced was copied // into a new instance of Bar and $blarg now holds a reference // to that new instance
Разница между
$assigned = $instance
а также
$assigned = clone $instance
заключается в том, что при использовании ключевого слова clone вы можете использовать магический метод __clone (), который дает вам лучший контроль над клонированием объектов. Из руководства php:
После завершения клонирования, если метод __clone () определен, тогда будет вызываться метод __clone () вновь созданного объекта, чтобы разрешить любые необходимые свойства, которые необходимо изменить.
Более того, объекты в PHP 5 назначаются по ссылке, если вы хотите создать копию объекта, который вы должны использовать клон .
Из руководства :
Ссылка PHP – это псевдоним, который позволяет двум различным переменным писать одно значение. Начиная с PHP 5, объектная переменная больше не содержит объект как значение. Он содержит только идентификатор объекта, который позволяет объектным аксессуарам находить фактический объект. Когда объект отправляется аргументом, возвращенным или назначенным другой переменной, разные переменные не являются псевдонимами: они содержат копию идентификатора, которая указывает на тот же объект.
$assigned = $instance
Выше присваивается $ instance to $ assign, самый основной присваивающий.
$assigned = clone $instance
Это для клонирования объектов. Назначьте копию объекта $ instance to $ assign.
Без клонирования $ assign и $ instance имеют одинаковый идентификатор объекта, что означает, что они указывают на один и тот же объект.
ну, в основном эти переменные – не что иное, как указатели на пространство памяти, где находится объект. Если вы сохраните значение указателя в другом указателе, а затем сбросьте исходный указатель, ничего не произойдет с областью памяти, на которую они оба указали.
Хранение короткого и простого здесь:
Здесь $reference
похож на псевдоним объекта $instance
. Если изначально $assignment
и $reference
указывают на пространство данных для $instance
объекта $instance
.
И когда происходит изменение значения, которое указывает на $instance
оно будет изменено повсюду.
Но когда $instance = null
, здесь мы делаем $instance
указывающий на null
и поскольку $reference
является псевдонимом, поэтому:
$ reference -> $ instance -> null ….
В то время как $assignment
прежнему содержит указатель на пространство данных для объекта, созданного $instance
, но теперь $instance
больше не нуждается в том же.
PHP не управляет объектами так же, как управляет другими типами данных. Строка (или целое число, логическое значение, float или массив) непосредственно сохраняется в переменной. Когда значение переменной присваивается другой переменной, значение копируется 1 в новую переменную.
Например:
$x = array('a'); $y = $x; // $x and $y are different and unrelated variables; they do not share anything $y[] = 'b'; print_r($y); // Array // ( // [0] => a // [1] => b // ) print_r($x); // Array // ( // [0] => a // )
С другой стороны, объекты обрабатываются PHP с использованием уникальных идентификаторов. Когда объект присваивается переменной, идентификатор хранится в переменной, а не в фактическом объекте.
Когда значение переменной присваивается другой переменной, идентификатор копируется, а не сам объект. Это приводит к тому, что две переменные указывают на один и тот же объект.
Используя ваш пример, значения переменных $instance
и $assigned
равны, оба они содержат идентификатор одного и того же объекта. $reference
, с другой стороны, является ссылкой, то есть псевдоним (другое имя) переменной $assigned
. Вот почему оператор $instance = null;
очищает содержимое переменных $reference
и $assigned
но не влияет на $instance
переменной $instance
а также объект, чей идентификатор хранится в нем.
Перед установкой $reference
на null
можно использовать любой из $instance
, $assigned
SimpleClass
или reference
для доступа к объекту SimpleClass
созданному в первой строке вашего примера. Fe:
$instance = new SimpleClass(); $assigned = $instance; $instance->var = '$assigned will have this value'; echo($instance->var); // It prints: // $assigned will have this value // $assigned is also modified because it is the same object echo($assigned->var); // It prints: // $assigned will have this value
Подробнее о объектах и ссылках PHP в документации.
$assigned = clone $instance
? Оператор clone
создает дубликат его операнда. Он создает новый объект и инициализирует все его свойства, присваивая им значения свойств исходного объекта. Это означает, что если объект clone содержит объекты как свойства, эти свойства дублируются простым присваиванием, а не клонированием. 2
$assigned = clone $instance;
После этого утверждения $assigned
содержит другое значение, чем $instance
потому что теперь они хранят идентификаторы разных объектов. Будучи разными объектами, изменения $instance
не влияют на $assigned
больше.
$instance = new SimpleClass(); $instance->var = '$instance has this value'; $assigned = clone $instance; echo($assigned->var); // It prints: // $instance has this value $assigned->var = '$assigned has a different value'; echo($assigned->var); // It prints: // $assigned has a different value // $instance is not modified echo($instance->var); // It prints: // $instance has this value
1 Это не совсем так. Для целей оптимизации массивы не копируются до тех пор, пока они не будут изменены (копирование при записи). Тем не менее, это подробная информация о реализации, и для этой дискуссии хорошо учитывать все значения, за исключением того, что объекты копируются, когда они назначены новой переменной.
2 Это также называется «мелким» клонированием. Чтобы получить «глубокий» клон (настоящий дубликат, который не имеет ничего общего с оригиналом), класс клонированного объекта, который имеет объекты как свойства, должен реализовать магический метод __clone()
и клонировать свойства оригинала объект. Кроме того, классы этих свойств должны реализовывать __clone()
и т. Д.
Он просто создает совершенно новый объект, который сохраняет свойства копируемого объекта. Он выполняет глубокую копию:
$assigned = $instance;
Это делает мелкую копию при копировании объекта из одного в другой:
$assigned = clone $instance;