2014-10-02 31 views
8

我正在閱讀這篇關於PHP變量引用的文章:http://derickrethans.nl/talks/phparch-php-variables-article.pdf 並且想要檢查我的理解是否正確,關於何時創建新的變量容器。PHP引用如何在數組的引擎下工作?

對於非數組,只要您指定一個未指向帶is_ref集的容器的變量,就會創建變量容器。

Ex 1 (let {..} be a container): 
$a = 1;  // "a" => {integer, 1, is_ref = 0, ref_count = 1} 

$b = $a; // "a", "b" => {integer, 1, is_ref = 0, ref_count = 2} 

$b = 2;  // "a" => {integer, 1, is_ref = 0, ref_count = 1} 
      // "b" => {integer, 2, is_ref = 0, ref_count = 1} 

Ex 2: 
$a = 1;  // "a" => {integer, 1, is_ref = 0, ref_count = 1} 

$b = &$a; // "a", "b" => {integer, 1, is_ref = 1, ref_count = 2} 

$b = 2;  // "a", "b" => {integer, 2, is_ref = 1, ref_count = 2} 

它是如何工作的數組?它看起來不一樣適用。例如,

$a = array(1, 2, 3); 
$b = $a; 
$c = &$b[2]; 
$c = 4; 
print_r($a); // prints (1, 2, 3) instead of (1, 2, 4) 
print_r($b); // prints (1, 2, 4) 

我的期望:

$ a和$ b指向同一個容器中。在這個容器中,我們有3個numeric_keys「0」,「1」,「2」分別指向整數1,2和3的容器。

當我們做$c = &$b[2],我們更新包含整數3的容器:

  • is_ref = 0變爲is_ref = 1
  • ref_count = 1變成ref_count = 2

在做$c = 4,我們更新容器中包含整數3:

  • inte由於is_ref已設置,ger 3變爲整數4

但是,由於$a[2] != 4在末尾,所以出現了一些問題。我試圖找出原因。我最好的猜測是,當我們嘗試引用數組的元素或對象的屬性時,PHP引擎首先檢查數組/對象本身以查看is_ref = 1。如果是,則所有事情都按照我的期望工作。如果is_ref = 0,則發生其他事情,這就是我所看到的。有人可以讓我知道那個「別的東西」是什麼嗎?

編輯 看起來這是實際發生的事情。這段代碼應該澄清一切!

$a = array(1, 2, 3); 
$b = $a; 
$c = &$b[2];  // $b points to a new container where $b[0], $b[1] still point to same container as $a[0], $a[1], but $b[2] points to a new container also pointed to by $c 
$d = $b;  // $d points to $b's container, this means changing $c will also change $d[2]  
$d[0] = 5;  // The container pointed to by $d[0] is the same as the one pointed to by $a[0] and $b[0]. Since this container has is_ref = 0, $d[0] will now point to a new container 

// At this point $a = (1, 2, 3), $b = (1, 2, 3), $c = 3, $d = (5, 2, 3) 

$d[2] = 25;  // The container pointed to by $d[2] is the same as the one pointed to by $b[2] and $c. Since this container has is_ref = 1, Changing $d[2] will affect both $b[2] and $c. 

// At this point $a = (1, 2, 3), $b = (1, 2, 25), $c = 25, $d = (5, 2, 25) 

$e = $d[2];  // Since $d[2]'s container has is_ref = 1, $e will point to its own container 

$c = 4;   // Same idea as $d[2] = 25; except $e won't get affected 

// At this point $a = (1, 2, 3), $b = (1, 2, 4), $c = 4, $d = (5, 2, 4), $e = 25 

// only way to have $d[2] be different from $b[2] is to make the container's is_ref = 0 
unset($b[2]); 
unset($c); 
$b[2] = $d[2]; 
$d[2] = 55; 

// At this point $a = (1, 2, 3), $b = (1, 2, 4), $d = (5, 2, 25), $e = 25 
+0

我不是100%確定,但我認爲'$ c = 4;'定義了變量的整數4。所以它不再持有指向'$ b [2]'的指針。所以'$ b [2]'不包含'4'是有道理的。 – 2014-10-02 21:04:23

+0

[數組鍵中的PHP引用]的可能重複(http://stackoverflow.com/questions/26098982/php-reference-in-array-key) – 2014-10-06 15:34:46

回答

2

創建$a什麼,這是一個簡單的變量。但是,當您創建$b時,默認情況下,PHP複製該變量。因此,$b現在與$a完全分開,就像它在您的第一個示例中一樣。

然後你設置$c等於參考$b[2]。所以他們都指向相同的內存地址。更新一個,它更新另一個。問題是你認爲$a也應該更新,但它不應該是因爲$b是它自己的變量。考慮一下,當我們改變$b一個參考$a

$a = array(1, 2, 3); 
$b = &$a; 
$c = &$b[2]; 
$c = 4; 
print_r($a); // prints (1, 2, 4) 
print_r($b); // prints (1, 2, 4) 

發生了什麼這就像你描述,因爲$b$a參考同樣的事情(從技術上$b現在是指向$a一個符號)

如果你想深入探究這個問題,這裏有一篇精彩的文章深入報道。 http://webandphp.com/how-php-manages-variables

+0

謝謝!這是一篇非常有用的文章。我已經更新了我的問題,正在發生什麼。希望這次我明白了。 – Popcorn 2014-10-03 01:23:20

+0

不是100%準確:'$ c = &$b[2];'是一種特殊情況:引用數組值實際上也使數組值成爲一個引用 – 2014-10-06 15:36:10