2014-03-13 30 views
0

爲什麼$assigned在我們將NULL分配給$instance時不會變爲NULL?當我們通過$instance->var更改$var的值時,$assigned將獲得新的更新值。爲什麼將這個被引用的對象設置爲NULL不會重置它的所有副本?

class SimpleClass 
{ 
    // property declaration 
    public $var = 'a default value'; 

    // method declaration 
    public function displayVar() { 
     echo $this->var; 
    } 
} 

$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); 

輸出:

NULL 
NULL 
object(SimpleClass)#1 (1) { 
    ["var"]=> 
    string(30) "$assigned will have this value" 
} 

我使用PHP 5.5.9。

+0

「爲什麼$分配NULL不會成爲NULL,當我們將NULL分配給$ instance?」因爲它們是兩個完全不同的變量,並且$分配既不知道也不關心你對$ instance做什麼。 – Boann

+0

很長一段時間以來,您已獲得本網站最好的答案之一 - 謹慎回覆作者,或者至少接受它? – halfer

+0

繼續從你不回覆我,或下面的優秀答案,我已經downvoted。 – halfer

回答

0

我認爲這是因爲對象本身在爲其標識符指定空值後仍然完好無損。當你設置一個對象的字段 - 它駐留在對象的內存部分,但是當你設置它的「指針」另一個值時 - 它駐留在別的地方,所以對象本身仍然存在,並且可以被另一個標識符引用指針)。

這裏是一個參考:php.net

8

的基礎

要了解發生了什麼,你需要挖掘到PHP的內部,看看內存管理。

引擎蓋下,一個值表示這樣的:的指向此值的變量

+--------------------+ 
| (type) {{ VALUE }} | 
| refcount = a  | 
| isref = b   | 
+--------------------+ 

基準計數器a計數的數目。 isref標誌顯示該值是按值(即$a = VALUE)還是通過引用(即$a =& VALUE)分配的。

假設下面的情況:

    +--------------------------+ 
$a ------------->| (int) 58     |   $a = 58 
       | refcount = 1 ; isref = 0 | 
       +--------------------------+ 

如果複製的$a價值爲$b,PHP只是遞增refcount中爲了節省內存(即不存儲兩次相同的值):

    +--------------------------+ 
$a -------+----->| (int) 58     |   $b = $a 
      |  | refcount = 2 ; isref = 0 | 
      |  +--------------------------+ 
      | 
      | 
$b -------+ 

如果你改變$ b的值到別的東西,將創建一個新的價值,並引用計數到58遞減:

    +--------------------------+ 
$a ------------->| (int) 58     |   $b = 'hello' 
       | refcount = 1 ; isref = 0 | 
       +--------------------------+ 

       +--------------------------+ 
$a ------------->| (string) 'hello'   | 
       | refcount = 1 ; isref = 0 | 
       +--------------------------+ 

在參考的情況下,isref標誌被設置爲true,和一個變化的影響都標識符:

    +--------------------------+ 
$a -------+----->| (int) 58     |   $b =& $a 
      |  | refcount = 2 ; isref = 1 | 
      |  +--------------------------+ 
      | 
      | 
$b -------+ 

    +--------------------------+ 
$a -------+----->| (int) 21     |   $b = 21 
      |  | refcount = 2 ; isref = 1 | 
      |  +--------------------------+ 
      | 
      | 
$b -------+ 

關於對象引用

你經常能聽到,在PHP中,對象是通過引用透明地傳遞。 According to the doc,這不完全正確。名稱標識符$a包含一個對象標識符,這就是函數之間傳遞的內容。我會說明這個標識符與下面object類型的整數,我不知道該怎樣它的真正的引擎蓋下完成的想法,但解釋持有;-)

不要混淆標識,即變量名與對象標識符,即對象在內存中的編號。

    +--------------------------+ 
$a ------------->| (object) 547654764237685 |   $a = new FooBar(); 
       | refcount = 1 ; isref = 0 | 
       +--------------------------+ 

別的地方在內存中,PHP店我們只是標識547654764237685創建的FooBar實例。當您使用值(object) 547654764237685時,PHP會自動檢索所述對象並允許您透明地使用它。

那麼發生了什麼?

讓我們一行一行地檢查你的代碼。

您首先創建一個新的SimpleClass實例。

    +--------------------------+ 
$instance ------>| (object) 547654764237685 |   $instance = new SimpleClass(); 
       | refcount = 1 ; isref = 0 | 
       +--------------------------+ 

然後你做一個值分配給$assigned,即遞增refcount

    +--------------------------+ 
$instance ---+-->| (object) 547654764237685 |   $assigned = $instance; 
      | | refcount = 2 ; isref = 0 | 
      | +--------------------------+ 
      | 
      | 
$assigned ---+ 

第三行引用$reference$instance。因爲價值的refcount大於一和,因爲它不是已經是一個參考(isref = 0),PHP在內存中創建一個新的類似的價值:

    +--------------------------+ 
$instance ---+-->| (object) 547654764237685 |   $reference =& $instance; 
      | | refcount = 2 ; isref = 1 | 
      | +--------------------------+ 
      | 
      | 
$reference --+ 

       +--------------------------+ 
$assigned ------>| (object) 547654764237685 | 
       | refcount = 1 ; isref = 0 | 
       +--------------------------+ 

的三個標識符$instance$assigned$reference評估,以非常相同對象,因爲對象標識符保持不變。儘管如此,我們現在在內存中有兩個不同的值。

這就是爲什麼電話$instance->var = '$assigned will have this value';影響$instance->var,$assigned->var$reference->var

現在,當您設置$instancenull,因爲$reference引用相同的值,都受到影響:

    +--------------------------+ 
$instance ---+-->| (NULL)     |   $instance = null; 
      | | refcount = 2 ; isref = 1 | 
      | +--------------------------+ 
      | 
      | 
$reference --+ 

       +--------------------------+ 
$assigned ------>| (object) 547654764237685 | 
       | refcount = 1 ; isref = 0 | 
       +--------------------------+ 

$assigned的對象引用不會受到影響,因爲它是一個單獨的值,從而$assigned仍會調用目的。

相關問題