2013-08-23 36 views
0

我有此PHP代碼PHP陣列基準

$a = array('one'); 

$b[0] = &$a[0]; 

$c = $a; 

$b[0] = 'three'; 

$a = array('two'); 

var_dump($a); echo '<br/>'; 

var_dump($b); echo '<br/>'; 

var_dump($c); echo '<br/>'; 

其輸出此 - >

array(1) { [0]=> string(3) "two" } 

array(1) { [0]=> &string(5) "three" } 

array(1) { [0]=> &string(5) "three" } 

$ B和$一個點爲相同的值,但$ C不應指向相同的值,它應該有它自己的值的副本。然後,當我將$ b的值更改爲三時,我不明白爲什麼$ c的值也會發生變化。我怎樣才能防止這一點?此外,當我將$ a的值更改爲'two'時,爲什麼$ b也不會更改爲'two'?

在此先感謝。

+0

你想完成什麼?如果我們不知道你爲什麼首先參考,很難提供幫助。 –

+0

任何人都可以創建他們不理解的複雜代碼。與其弄清楚什麼不起作用,爲什麼不嘗試真正蒸餾你想做的事情,而是解決這個問題。哦,不要使用引用(作爲一般規則)... – ircmaxell

+0

這就是我正在做的。我必須動態地將變量綁定到mysqli_stmt :: bind_result,所以我這樣做, for($ i = 0; $ i <$ n_result; $ i ++){$ b_res [$ i] =&$ result [$ i] ; } call_user_func_array(array($ stmt,「bind_result」),$ b_res) 其中$ result是執行後返回的列數。然後,當我這樣做,while($ stmt-> fetch()){array_push($ r_val,$ b_res);} 我得到的是結果集的最後一行。這是因爲我發佈的問題而發生的。有沒有辦法我只能將值複製到新變量然後返回? – maurya8888

回答

-1

它們都指向同一個數組對象在內存

+0

如果他們都指向相同的對象,那麼爲什麼var_dump($ b)給出'三',它應該給'兩',因爲我已經將$ a的值更改爲'2' – maurya8888

3

您的問題是:

$b[0] = &$a[0]; 

此引用數組的第一個元素。由var_dump()輸出&string(5)明顯可見。因此$b不引用整個數組,只引用第一個元素。

要引用整個數組,你需要做的:像您期望

$b = &$a; 

這樣做的工作:

// $a 
array(1) { 
    [0]=> 
    string(3) "two" 
} 
// $b 
array(1) { 
    [0]=> 
    string(3) "two" 
} 
// $c 
array(1) { 
    [0]=> 
    string(3) "one" 
} 

瞭解更多關於Arrays in PHP

2

這是一步一步的解釋:

$a = array('one'); 
$b[0] = &$a[0]; 

$b現在是一個數組,它的第一個元素引用的$a第一個元素。在符號表中,$b[0]$a[0]指向相同的基礎zval。

$c = $a; 

$c引用$a了,但副本尚未作出(寫時拷貝語義)。它看起來像這個有很多:

$c ----/----> $a    $b 
(0: 'one') 0: 'one' <---- 0: 'one' 

下一個語句:

$b[0] = 'three'; 

這將更新$a[0]爲好,並依次更新$c[0],因爲$a本身並沒有改變。它現在看起來像;

$c ----/----> $a    $b 
(0: 'three') 0: 'three' <---- 0: 'three' 

下一頁聲明:

$a = array('two'); 

斷開$a$c$b[0]$a[0]

$c   $a  $b 
0: 'three' 0: 'two' 0: 'three' 

預防

爲了防止這種行爲,你需要引用整個數組只有一個元素,而不是:

$b = &$a; 

通過這樣做,$b$a現在引用同zval(數組本身),所以所做的任何更改都會將其從$c斷開。

我會考慮這些邊緣情況下的語言,但我會建議不要使用引用,如果你不需要。

+0

我不明白爲什麼$ c = $ a不會複製該值,而是創建一個參考。有沒有什麼我可以在這裏做的,所以它不是一個參考?顯然這是我可以在代碼中改變的唯一東西。 – maurya8888

+1

@ maurya8888我已經更新瞭如何防止的答案。當然,如果你完全不使用引用,你將永遠不會有這個問題:) –

+0

@Jack,我猜他們是從C引用他們引用數組的方式。 –

1

當通過參考值與值分配時,理解你在做什麼很重要。我們一行一行地去。

$a = array('one'); 

創建了存儲位置,我們稱之爲M1。 $ 1分給M1,在M1內我們有一個1入口的數組,我們稱之爲M1-A1。

$b[0] = &$a[0]; 

現在我們正在做的是將$ b [0]指向M1-A1。請記住,$ a [0]也指向M1-A1,所以它們都指向這部分內存。請記住,$ b本身具有自己的內存位置M2,但在M2內我們指向M1-A1(即M2-A1指向M1-A1)。

$c = $a; 

,由於我們不是通過引用賦值,我們得到的是一個新的內存位置,讓我們稱之爲M3,但內M3有與第一個條目仍指向M1-A1的數組。

所以現在我們有M1,M2,M3,M2和M3中的數組條目指向M1-A1。由於$ b [0]實際上指向M1-A1,我們實際上正在改變M1-A1記憶點的值。所以任何引用M1-A1現貨的東西也會看到這個價值的變化。

$a = array('two'); 

這時我們完全改變了$ a的內存位置。原來它是M1,現在我們正在創建一個新的內存位置M4。沒有別的指向M4和M4-A1不指向M1-A1。

所以當我們做var dump時,我們得到了你提到的值。

我可能使這個更混亂,但試着在紙上畫出來,它會很清楚。理解一切都存儲在內存中,變量只是指向內存位置。一旦你理解了這個原則,它就會落到實處。

+0

太棒了!現在,我可以做些什麼,以便M3不會指向M1-A1,而只是將值保留在M1-A1中。例如 - 如果它是C我會使用*前$ a – maurya8888

+0

我看到的一個小嘀嗒是將數組傳遞給一個函數。 PHP會自動刪除引用並將其設置爲值。所以如果我們做了$ c = $ a; $ c = array_flip(array_flip($ c));那麼我們將把$ a中的所有內容作爲值並且不再有任何引用。 (你不必使用array_flip,它只是一個示例函數) – SaidK

+0

是的,像$ c = json_decode(json_encode($ a))這樣的技巧。 – maurya8888