2010-07-01 43 views
2

當從ref函數返回的值被分配給多個變量時,第一個之後的賦值似乎複製了該值。PHP:ref函數返回的值看起來會被複制到多個賦值中

我用來測試它的代碼是:

[email protected]:/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) 

相同的代碼,格式化,並帶有註釋:

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 

沒有任何理由只有第一項任務是裁判,而其他被返回複製?

爲了便於比較,這是當值不是一個函數的返回會發生什麼:

[email protected]:/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) 

相同的代碼,格式:

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) 

正如你所看到的,幾乎沒有使用內存通過參考進行多個分配。

在發佈到bugs.php.net之前,我想知道它是否是我不知道的預期行爲。任何人都知道它爲何發生?

+0

*(參考)* [寫入時複製在PHP語言(PDF)(http://www.trl.ibm.com /people/mich/pub/200901_popl2009phpsem.pdf) – Gordon 2010-07-01 20:46:16

回答

3

該功能和呼叫都需要&。所以下面

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(54296) 
int(7843472) 
int(7843520) 
int(7843520) 
int(7843544) 
+0

太好了,謝謝。 我還是不太明白爲什麼用&定義函數是不夠的?它不應該告訴PHP通過引用返回它嗎?功能和foo告訴它做什麼,而不是? 另外,爲什麼第一個作業按我的預期工作,只有第二個作業開始複製它? – shesek 2010-07-01 20:30:40

+0

另一件事 - 即使沒有任何「&」,不在函數定義中,也不在調用它時 - 不應該通過引用將它複製並僅在修改某些內容時複製它。 – shesek 2010-07-01 20:32:47

+0

我的理解是,&上的函數告訴解釋器它可以通過引用返回,並且集合上的那個本身說明你正在通過引用進行設置。至於第一和第二的區別,我不能評論,因爲我不確定。 在你的第二個評論,因爲它來自一個函數解釋器將它們視爲var的單獨「實例」,因爲函數沒有設置爲通過引用返回。 希望這爲你清除了一點點 – 2010-07-02 01:35:56