As I am going through PHP manual ( http://php.net/manual/en/language.oop5.basic.php ), I came across the following confusion:
When assigning an already created instance of a class to a new variable, the new variable will access the same instance as the object that was assigned.
And below manual contains the following example:
<?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);
?>
With output
NULL
NULL
object(SimpleClass)#1 (1) {
["var"]=>
string(30) "$assigned will have this value"
}
Shouldn't 3rd case be also NULL if
the new variable will access the same instance as the object that was assigned
Otherwise it seems that $assigned is passed by value, not reference if the first initiator ($instance) was set to NULL and $assigned didn't change its value.
A variable that contains an object actually just contains an object reference . Think of every instantiated object as living in some pool of objects somewhere behind the scenes, and a variable just holding something like "object#3", a reference to the object.
If you assign this object reference to another variable via =
, a copy of this reference is made. Now two variables hold a copy of "object#3", which obviously refers to the same object.
Assigning by reference using =&
makes two variables point to the same reference, so anything changing that reference (like overwriting it with null
) will influence both variables. The object still continues to exist behind the scenes though, another variable holding another reference to it is not affected.
UPDATE: modified the diagram and the explanation to reflect more accurate what happens under the hood.
In computer languages, the variables are named memory locations that are used to store values. On compiled languages, the names of the variables usually vanish at the compile time; they are just language aids for the programmers. The interpreted languages keep the variable names because they need them at the runtime.
PHP stores the values of simple types (bool, integer, float, string) in variables; it has a different way to store the objects: a separate memory block is allocated to store the object data and the variable holds a reference/pointer to the object data (the address in memory where the object data is stored).
Object assignment does not duplicate the object data; it just copies the address of the data into a new variable. In order to duplicate an object's data, one must use the clone
operator like this:
$duplicate = clone $instance;
The code:
$instance = new SimpleClass();
$assigned = $instance;
$reference =& $instance;
$duplicate = clone $instance;
$number = 123;
produces something like this in memory:
$instance
$reference
+----------------------+ +----------------------------+
| address of object #1 | --------> | SimpleClass object #1 data |
+----------------------+ +----------------------------+
^
$assigned |
+----------------------+ |
| address of object #1 | ------------------------+
+----------------------+
$duplicate
+----------------------+ +----------------------------+
| address of object #2 | --------> | SimpleClass object #2 data |
+----------------------+ +----------------------------+
$number
+------+
| 123 |
+------+
The rectangles are memory locations used to store data; some of them have names displayed above them (the variables), others do not (memory blocks that store the objects data).
How it works:
$instance = new SimpleClass();
allocate a block of memory to store a new object of type SimpleClass
and store a reference to it (its memory address) in the variable $instance
; $assigned = $instance;
copies the value stored in variable $instance
(ie the reference to the object) into the new variable $assigned
; this means $assigned
points to the same object of type SimpleClass
as $instance
; accessing the object's properties using $instance->var
or $assigned->var
is the same thing because they both point to the same instance of the SimpleClass
type; $reference = & $instance;
adds a new name ( $reference
) to the memory location (variable) identified by name $instance
; $duplicate = clone $instance;
is similar with $instance = new SimpleClass();
but the newly created object is not initialized by calling its constructor; instead, the data of the object referenced by $instance
is copied into the new object then its method __clone()
is invoked, if exists; $instance = NULL;
will replace the content of variable $instance
with NULL
(stops pointing to the SimpleClass
object #1) but it will not affect either $assigned
(it's a different variable) or the SimpleClass
object #1 itself; the object can still be accessed through variable $assigned
; $reference
will have the same value as $instance
because they are just names for the same memory location (that stores NULL
now). The data structures now looks like:
$instance
$reference
+-------------------+ +----------------------------+
| NULL | | SimpleClass object #1 data |
+-------------------+ +----------------------------+
^
$assigned |
+----------------------+ |
| address of object #1 | ------------------------+
+----------------------+
$duplicate
+----------------------+ +----------------------------+
| address of object #2 | --------> | SimpleClass object #2 data |
+----------------------+ +----------------------------+
$number
+------+
| 123 |
+------+
unset($instance);
just removes the name $instance
from the variable; because it still has another name ( $reference
) the variable still exists and it can be accessed and modified using its other name. When $reference
is also unset the variable cannot be accessed any more and the memory it uses will be released on the next garbage collection cycle. The same happens when $assigned
is unset (both the variable and the object data become inaccessible and they will be released).
First :-
PHP user refrence counting scheme for Garbage collection, mean every time when you assign a object variable to another you are increasing that counter by 1 and every time when a variable goes out of scope, counter will decrease by 1
Second :- ( passing variables by refrence )
$a = 5; // consider the memory address of $a is 25 or we can say that "$a" is a pointer that point to location 25, so every time when we assign somethig in it or assining it to other we are fetching the value of the location of this variable,
same as
$b = 10; // may be internally memory address is 26
but the important thing is :
$a = 10; // memory address 25 $b = &$a; // $b's memory address is also 25
so if i write $a = 11; so $b's value will also change became they are the name of the same memory location so when i change one it affect other also,,
Now talk about this problem :-
$instance = new SimpleClass();
here a object create in memory, we can name it 'x' on address 'x_address' and a variable also create name $instance that's location is 'instance_address' that contain the value 'x_adderss' and Refrence table look like this :-
RefrenceTable :-
object | refrence_count | memory_address
| |
'x' | 1 | 'x_address'
and Variable stack look like this :-
Stack :-
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | 'x_address'
Now next statement
$assigned = $instance;
Variable Stack :-
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | 'x_address'
assigned | 'assigned_address' | 'x_address'
and
RefrenceTable :-
object | refrence_count | memory_address
| |
'x' | 2 | 'x_address'
Because now 2 varialbe refrencing that object, so this object only will garbage when both will be goes out of scope
Next statement
$reference = & $instance; // One of the most important line
Variable Stack :-
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | 'x_address'
assigned | 'assigned_address' | 'x_address'
refrence | 'instance_address' | 'x_address' // because pointing the same
// memory as instance
RefrenceTable :-
object | refrence_count | memory_address
| |
'x' | 2 | 'x_address'
Notice no refrence _count increased, because that varialbe that point to some location,, In other words we can say that now we can point location -> 'instance_address' with 2 names
Next Statement :
$instance->var = '$assigned will have this value'; // Not so some changed happend in 'x_address'
Next Statement :
$instance = null; // one
of the important line
Variable Stack :-
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | NULL
assigned | 'assigned_address' | 'x_address'
refrence | 'instance_address' | NULL // because pointing the same
// memory as instance
Because instance and refrenced point to same location, if we change one values second will automaticallye changed, so both become null
But refrence_count of object 'x' will be decrease by 1
RefrenceTable :-
object | refrence_count | memory_address
| |
'x' | 1 | 'x_address'
so $assigned still point to object in memory,,
and when we will write like this :-
$assigned = null;
Then
Variable_name | Variable_address | Variable_value
| |
instance | 'instance_address' | NULL
assigned | 'assigned_address' | NULL
refrence | 'instance_address' | NULL // because pointing the same
// memory as instance
object | refrence_count | memory_address
| |
'x' | 0 | 'x_address' // Marked for Garbe collection
Thanks :) { Sorry for weak english, im not a native english speaker }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.