Reputation: 4650
First, sorry for the stupid question, but I was reading an article in php.net and I couldn't understand what exactly it says.
<?php
class SimpleClass
{
// property declaration
public $var = 'a default value';
// method declaration
public function displayVar() {
echo $this->var;
}
}
?>
<?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);
?>
And this outputs this:
NULL
NULL
object(SimpleClass)#1 (1) {
["var"]=>
string(30) "$assigned will have this value"
}
$instance and $reference point to same place, I get this and I understand why we get NULL and NULL for them.
But what about $assigned? It's it also pointing the place where $instance is stored? Why when we use $instance->var
it affects $assigned, but when we set $instance to be null, there is no change for $assigned?
I thought that the all three variables point to one place in the memory, but obviously I'm wrong. Could you please explain me what exactly happens and what is $assigned? Thank you very much!
Upvotes: 8
Views: 5238
Reputation: 13349
With the following line, we reserve a memory location, in which storing the new Object, and a pointer to it, labeled as $instance
:
$instance = new SimpleClass();
With the following line, we create a reference to the pointer $instance
, labeled as $reference
:
$reference =& $instance;
With the following line, we reserve a new memory location, labeled as $assigned
, different and indipendent from the one above, in which we store a copy of the pointer (not the object itself) created above:
$assigned = $instance;
By setting $instance
to null
, you will unset only the pointer to the memory location which contains the actual object, not the object itself. Any other reference to it (for instance, $reference
) will be unset as well.
$assigned
is an indipendent copy of the pointer (held in another memory location), which still points to the actual object.
This is why it can be still used to refer to the actual object.
This comment found in the PHP documentation comes in support of what above said:
<?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...
?>
Note
This represents a kind of exception when speaking about memory management. Whereas copying a variable or array is addressed just by to use the =
operator, with objects you shall explicitely use the clone
keyword, as stated in the PHP documentation:
An exception to the usual assignment by value behaviour within PHP occurs with objects, which are assigned by reference in PHP 5. Objects may be explicitly copied via the clone keyword.
Upvotes: 2
Reputation: 173552
Short answer, when you create a reference using &
, this is what happens:
$A ===+
|===> [symbol table entry x] ====> (memory location)
$B ===+
When you do a normal assignment after that:
$A ===+
|===> [symbol table entry x] ===> (memory location)
$B ===+ ^
|
$C =======> [symbol table entry y] ========+
Let's step through the code:
$instance = new SimpleClass();
$assigned = $instance;
Assertion:
$assigned === $instance
Both $assigned
and $instance
reference the same instance of SimpleClass
.
$reference =& $instance;
Assertion:
$assigned === $instance === $reference
All variables reference the same instance.
$instance->var = '$assigned will have this value';
Assertion:
$assigned === $instance === $reference
Even though a property of $instance
is changed, it doesn't affect the references.
$instance = null; // $instance and $reference become null
Because $reference
is just an alias in the symbol table, it gets the same value as $instance
; the reference count of the the original instance (i.e. memory location) gets reduced to 1, the $assigned
variable.
Upvotes: 1
Reputation: 141839
Setting $instance = null;
doesn't update $assigned
because it is not updating the data at the location where $instance
points. It is instead modifying the $instance
pointer itself so that pointer no longer points at the same data as $assigned
.
Upvotes: 4
Reputation: 5102
It's really simple:
$a = 3;
$b = $a;
$c = &$a;
$a = 0;
var_dump($a);
var_dump($b);
var_dump($c);
The output will be:
int(0)
int(3)
int(0)
So it not only object assignment but also normal assignment.
Upvotes: 0
Reputation: 116100
An object is a separate entity in memory which can have 1 or more references. If it got 0, it is garbage collected.
A variable containing an object actually points to (refers to) that object. So when you do this:
$var1 = new Object();
$var2 = $var1;
you just create two variables, pointing to the same object ($var2 copies the value of $var1, but that value is the reference to the object).
If you then write, $var1 = null
, you remove that one reference, but $var2 still points to the object.
The & operator actually returns a reference to the variable behind it, so when you write
$var1 = &var2;
then $var1 doesn't point to the object to which $var2 points as well, but $var1 points to $var2 itself. So when you make $var2 null, $var1 points to that same null.
Upvotes: 2
Reputation: 1057
As you can see in the code
$instance = null; // $instance and $reference become null
$instance has now become equal to null, but before then $assigned was set. so $assigned did not get the null value. $reference received the null value because you referenced it with =& it keeps the value of $instance.
Upvotes: 0
Reputation: 33358
$reference
points to the value of $instance
, which is itself a reference to an object. So when you change the value contained by $instance
, $reference
reflects this change.
$assigned
, on the other hand, is a copy of the value of $instance
, and independently points to the object itself to which $instance
refers. So when the value $instance
is updated to point to nothing (i.e. null
), $assigned
is not affected, since it still points to the object, and doesn't care about the contents of $instance
.
Upvotes: 7