php中foreach對陣列指標的影響及原因

2021-07-07 04:13:35 字數 2333 閱讀 7132

問題描述:遍歷陣列時,改變了陣列的值,陣列遍歷完成後,陣列的指標指向了第二個元素,當發生這種情況時,會對後續通過指標遍歷陣列產生影響。

<?

$arrd = array('0'=>'a','1'=>'b','2'=>'c');

echo key($arrd)."

";foreach($arrd as $intk => $val)

echo(key($arrd));

?>

輸出結果如下:

0

1

因此再次通過指標遍歷陣列的時候會發現$arrd的第乙個值就迴圈不出來了。

其實問題很好解決,在foreach之後,直接用reset()方法將$arrd的指標重置一下就可以了,但導致問題的原因才是值得關注的,在做了一些搜尋和閱讀的工作之後,總結問題原因如下,首先,先知道幾個php處理賦值遍歷等動作的原則:

1,php在變數賦值時候的記憶體使用策略:寫時複製(copy on write, cow),當用賦值方法把乙個變數值賦給另乙個變數時,由於這兩個變數值相同,因此公用同一記憶體,當其中乙個變數值發生變化時候,才會重新為值變化的變數申請記憶體,已達到節省記憶體的目的;

2,foreach遍歷陣列時,實際上是遍歷的陣列的乙個拷貝,並且在開始遍歷之前會把指標指向拷貝的開始;

3,在發生寫時複製時候,指標的位置也會一併被複製;

針對規則1 的驗證

<?

echo "初始記憶體情況:".memory_get_usage()."

";$foo = str_repeat('aaa', 10000);

echo "使用變數\$foo之後的記憶體:".memory_get_usage()."

";$bar = $foo;

echo "將變數\$foo拷貝給\$bar後的記憶體:".memory_get_usage()."

";$bar = str_repeat('aaa', 10000);

echo "對\$bar值修改後使用的記憶體:".memory_get_usage()."

";?>

輸出結果如下:

初始記憶體情況:118912

使用變數$foo之後的記憶體:149008

將變數$foo拷貝給$bar後的記憶體:149056

對$bar值修改後使用的記憶體:179104

針對規則2的驗證

<?

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

next($a);

foreach($a as $v)

?>

輸出結果如下

a

bc

針對規則3的驗證

<?

$a = array (1,2,3);

next($a);

$b = $a;//同一記憶體

$b = 4;//$b被開闢了新的儲存空間,指標與之前儲存空間的一致

echo current($b);

?>

輸出結果如下

2

然後來看產生最初問題的原因:

1. foreach 迴圈遍歷 $arrd 時,php建立了乙個 $arrd 的拷貝aa是不可見的,只是為了描述方便 ),但是由於此時a和 $arrd 值一樣,所以,共用同乙個記憶體;

2.執行 foreach時候,先把a中第乙個指標所在的keyvalue分別賦值給 $a 和 $b,同時指標後移一位,由於此時a和 $arrd 共用同一記憶體,此時 $arrd 的指標也指向了第二個值;

3.當執行到$a = 'd';時,由於 $arrd 的值發生改變,此時系統給 $arrd分配了其他記憶體,而同時,其指標指向也被拷貝到新記憶體中;而之後的遍歷過程中,a$arrd相當於兩個完全不同的變數,不同值,不同儲存位址,a指標的移動已經無法影響 $arrd 指標的變化,因此當 a 被遍歷完成後,$arrd的指標仍然被留在第二個值的位置。

PHP對陣列兩次foreach的使用陷阱

1.兩次迴圈如果不實用引用列印結果沒有任何問題 array a b c foreach array as value foreach array as value var dump array 執行結果 array 3 2.當第一次迴圈使用引用後會出現如下bug 如下 array a b c for...

PHP 陣列 foreach用法

foreach用於陣列 foreach僅能用於陣列,每次迴圈中,當前單元的鍵名也會在每次迴圈中被賦給變數 key。當前單元的值被賦給 value 並且陣列內部的指標向前移一步。有兩種語法 foreach array expression as value statement foreach arra...

PHP中對陣列進行排序

測試一 array array array id 1,name a array id 5,name b array id 3,name c 按列id的值進行排序 foreach array as key row 把 data 作為最後乙個引數,以通用鍵排序 print r array array m...