2011-02-11 48 views
28
<?php 
    $a = array('a', 'b', 'c', 'd'); 

    foreach ($a as &$v) { } 
    foreach ($a as $v) { } 

    print_r($a); 
?> 

Tôi nghĩ rằng đó là một chương trình bình thường nhưng điều này là kết quả tôi nhận được:hành vi kỳ lạ của foreach

Array 
(
    [0] => a 
    [1] => b 
    [2] => c 
    [3] => c 
) 

Ai đó có thể xin giải thích này với tôi?

+4

* "Tôi nghĩ, prog bình thường của nó nhưng web tôi thấy op ......... sau đó .... ahh wat là nó" * nghĩa là gì? –

+0

Tôi tự hỏi !!! Tại sao có được kết quả này ?? :) –

+1

@Bart Kiers: Anh ta có vẻ ngỡ ngàng. – BoltClock

Trả lời

67

hành vi PHP được cũng như các tài liệu này Xem warning trên trang foreach của php.net

Warning

tham khảo của một $ value và phần tử mảng cuối cùng vẫn còn sau vòng lặp foreach. Bạn nên hủy nó bằng cách unset().

$a = array('a', 'b', 'c', 'd'); 

foreach ($a as &$v) { } 
unset($v); 
foreach ($a as $v) { } 

print_r($a); 

EDIT

Cố gắng ở một hướng dẫn từng bước với những gì đang thực sự xảy ra ở đây

$a = array('a', 'b', 'c', 'd'); 
foreach ($a as &$v) { } // 1st iteration $v is a reference to $a[0] ('a') 
foreach ($a as &$v) { } // 2nd iteration $v is a reference to $a[1] ('b') 
foreach ($a as &$v) { } // 3rd iteration $v is a reference to $a[2] ('c') 
foreach ($a as &$v) { } // 4th iteration $v is a reference to $a[3] ('d') 

          // At the end of the foreach loop, 
          // $v is still a reference to $a[3] ('d') 

foreach ($a as $v) { } // 1st iteration $v (still a reference to $a[3]) 
          // is set to a value of $a[0] ('a'). 
          // Because it is a reference to $a[3], 
          // it sets $a[3] to 'a'. 
foreach ($a as $v) { } // 2nd iteration $v (still a reference to $a[3]) 
          // is set to a value of $a[1] ('b'). 
          // Because it is a reference to $a[3], 
          // it sets $a[3] to 'b'. 
foreach ($a as $v) { } // 3rd iteration $v (still a reference to $a[3]) 
          // is set to a value of $a[2] ('c'). 
          // Because it is a reference to $a[3], 
          // it sets $a[3] to 'c'. 
foreach ($a as $v) { } // 4th iteration $v (still a reference to $a[3]) 
          // is set to a value of $a[3] ('c' since 
          //  the last iteration). 
          // Because it is a reference to $a[3], 
          // it sets $a[3] to 'c'. 
+0

tôi biết điều đó !!! Nhưng có gì sai trong chương trình của tôi ??? –

+3

@Manish Trivedi: Xem phần ** Warning ** cho lý do tại sao điều này xảy ra. Không có gì sai với chương trình của bạn. – BoltClock

+0

Cảm ơn ..... tôi đã nhận nó –

2

Vòng lặp foreach đầu tiên không thực hiện bất kỳ thay đổi đến mảng, giống như chúng ta mong đợi. Tuy nhiên, nó gây ra $v được chỉ định tham chiếu đến từng yếu tố của $a, sao cho, khi vòng lặp đầu tiên kết thúc, thì thực tế, một tham chiếu đến $a[2].

Ngay khi vòng lặp thứ hai bắt đầu, $v hiện được gán giá trị của mỗi phần tử . Tuy nhiên, $v đã là tham chiếu đến $a[2]; do đó, mọi giá trị được gán cho nó sẽ được sao chép tự động vào phần tử cuối cùng của mảng!

Do đó, trong lần lặp đầu tiên, $a[2] sẽ trở thành 0, sau đó một, và sau đó một lần nữa, được sao chép hiệu quả vào chính nó. Để giải quyết vấn đề này, bạn luôn phải bỏ đặt các biến mà bạn sử dụng trong các tham chiếu của mình cho các tham chiếu vòng lặp — hoặc, tốt hơn, tránh sử dụng hoàn toàn các biến đó.