Skip to content

Instantly share code, notes, and snippets.

@kana
Created August 17, 2017 12:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kana/822bfed45e868ab9e78e729398a889ad to your computer and use it in GitHub Desktop.
Save kana/822bfed45e868ab9e78e729398a889ad to your computer and use it in GitHub Desktop.
Don't confuse PHP & reference with other languages' reference.
<?php
function test_copy_on_write()
{
print "test_copy_on_write\n";
$a = 100;
xdebug_debug_zval('a');
//==> a: (refcount=1, is_ref=0)=100
$b = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
//==> a: (refcount=2, is_ref=0)=100
//==> b: (refcount=2, is_ref=0)=100
// ($a and $b point the same value.)
$c = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
//==> a: (refcount=3, is_ref=0)=100
//==> b: (refcount=3, is_ref=0)=100
//==> c: (refcount=3, is_ref=0)=100
// ($a, $b and $c point the same value.)
$a++;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
//==> a: (refcount=1, is_ref=0)=101
//==> b: (refcount=2, is_ref=0)=100
//==> c: (refcount=2, is_ref=0)=100
// ($a points a different value because of copy-on-write.)
// ($b and $c still point the same value.)
unset($c);
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
//==> a: (refcount=1, is_ref=0)=101
//==> b: (refcount=1, is_ref=0)=100
//==> c: no such symbol
// (The refcount of the value pointed by $b is decremented, because $c is unset.)
}
function test_no_copy_on_write_for_reference()
{
print "test_no_copy_on_write_for_reference\n";
$a = 100;
xdebug_debug_zval('a');
//==> a: (refcount=1, is_ref=0)=100
$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
//==> a: (refcount=2, is_ref=1)=100
//==> b: (refcount=2, is_ref=1)=100
// ($a and $b point the same value.)
$a++;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
//==> a: (refcount=2, is_ref=1)=101
//==> b: (refcount=2, is_ref=1)=101
// ($a and $b point the same value even after modification.)
}
function test_but_copy_on_assignment_from_referenct_to_value()
{
print "test_but_copy_on_assignment_from_referenct_to_value\n";
$a = 100;
xdebug_debug_zval('a');
//==> a: (refcount=1, is_ref=0)=100
$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
//==> a: (refcount=2, is_ref=1)=100
//==> b: (refcount=2, is_ref=1)=100
// ($a and $b point the same value.)
$c = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
//==> a: (refcount=2, is_ref=1)=100
//==> b: (refcount=2, is_ref=1)=100
//==> c: (refcount=1, is_ref=0)=100
// ($a and $b point the same value.)
// (But $c is a copy of that value, because changes to $a/$b must not be shared with $c.)
}
function test_reference_becomes_non_reference()
{
print "test_reference_becomes_non_reference\n";
$a = 100;
xdebug_debug_zval('a');
//==> a: (refcount=1, is_ref=0)=100
$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
//==> a: (refcount=2, is_ref=1)=100
//==> b: (refcount=2, is_ref=1)=100
// ($a and $b point the same value.)
$a++;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
//==> a: (refcount=2, is_ref=1)=101
//==> b: (refcount=2, is_ref=1)=101
// ($a and $b point the same value even after modification.)
unset($);
xdebug_debug_zval('a');
xdebug_debug_zval('b');
//==> a: (refcount=1, is_ref=0)=101
//==> b: no such symbol
// (Note that is_ref is changed to 0.)
// (Because PHP's & reference is meaningful if two or more variables share the same value)
}
test_copy_on_write();
test_no_copy_on_write_for_reference();
test_but_copy_on_assignment_from_referenct_to_value();
test_reference_becomes_non_reference();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment