views:

32

answers:

1

When a value being returned from a function by ref is assigned to multiple variables, assignments after the first one seems to copy the value.

The code I used to test it is:

root@kelso:/tmp# php -r 'function &bar() {static $x; if (NULL === $x) {$x=range(1,99999);}; return $x;};  var_dump(memory_get_usage()); bar(); var_dump(memory_get_usage()); $b1=bar(); var_dump(memory_get_usage()); $b2=bar(); var_dump(memory_get_usage()); $b3=bar(); var_dump(memory_get_usage());'  
int(95872)  
int(20345912)  
int(20346040)  
int(33395000)  
int(46444184)

Same code, formatted and with comments:

function &bar() {static $x; if (NULL === $x) {$x=range(1,99999);}; return $x;};  
var_dump(memory_get_usage()); // starting out with 95872  
bar();  
var_dump(memory_get_usage()); // 20345912 - first call to bar() sets the static $x  
$b1=bar();  
var_dump(memory_get_usage()); // 20346040 - first assignment consumes almost no memory  
$b2=bar();  
var_dump(memory_get_usage()); // 33395000 - second assignment seems to copy it  
$b3=bar();  
var_dump(memory_get_usage()); // 46444184 - third assignment seems to copy it again

Is there any reason only the first assignment is returned by ref while other are copied?

For comparison, this is what happens when the value is not returned from a function:

root@kelso:/tmp# php -r 'var_dump(memory_get_usage());; $a=range(1,99999); var_dump(memory_get_usage()); $b=&$a; var_dump(memory_get_usage()); $c=&$a; var_dump(memory_get_usage());'  
int(92224)  
int(20342024)  
int(20342152)  
int(20342280)  

Same code, formatted:

var_dump(memory_get_usage()); // int(92224)  
$a=range(1,99999);  
var_dump(memory_get_usage()); // int(20342024)  
$b=&$a;  
var_dump(memory_get_usage()); // int(20342152)  
$c=&$a;  
var_dump(memory_get_usage()); // int(20342280)  

As you can see, almost no memory is used for multiple assignments by reference.

Before posting this to bugs.php.net, I was wondering if its an expected behavior that I don't know of. Anyone knows why it happens?

+3  A: 

The & is required for both the function and the call. So the following

function &bar() {
static $x; 
if (NULL === $x) {
    $x=range(1,99999);
}
return $x;}

var_dump(memory_get_usage());
bar();
var_dump(memory_get_usage()); 
$b1=&bar();  
var_dump(memory_get_usage()); 
$b2=&bar();  
var_dump(memory_get_usage()); 
$b3=&bar(); 
var_dump(memory_get_usage());

Will give you

int(54296)
int(7843472)
int(7843520)
int(7843520)
int(7843544) 
Christian South
shesek
shesek
Christian South
So basically copy-on-write doesn't work on values returned from a function, just when assigning one variable to another or on variables passed as arguments to a function? Any chance someone else might know the difference between the first assignment from a function to the next ones?
shesek