> 백엔드 개발 > PHP 튜토리얼 > PHP 루프의 '참조'로 인해 발생하는 이상한 문제

PHP 루프의 '참조'로 인해 발생하는 이상한 문제

WBOY
풀어 주다: 2016-07-25 08:46:29
원래의
995명이 탐색했습니다.

이 글은 stackoverflow 웹사이트의 글을 편집한 것입니다. 참조에 의한 루프 이후의 이상한 동작 - 이것은 PHP 버그인가요? PHP 루프에서 을 사용하여 을 참조하면 매우 이상한 동작이 발생합니다. 이것이 PHP의 버그입니까?

질문

간단한 PHP 스크립트를 작성하는 동안 매우 이상한 일이 일어났습니다. 다음은 제가 의미하는 바를 명확하게 표현하기 위해 의도적으로 불필요한 코드를 제거한 코드입니다.

  1. $arr = array("foo",
  2. "bar",
  3. "baz");
  4. foreach ($arr as &$item) { /* 참조로 아무것도 하지 않음 */ }
  5. print_r($arr);
  6. foreach ($arr as $item) { /* 참조로 아무것도 하지 않음 value */ }
  7. print_r($arr); // $arr가 변경되었습니다....왜?
코드 복사

출력은 다음과 같습니다.

  1. 배열
  2. (
  3. [0] => foo
  4. [1] => bar
  5. [2] => baz
  6. )
  7. 배열
  8. (
  9. [0] => foo
  10. [1] => bar
  11. [2] => bar // 오류가 발생했습니다??
  12. )
코드 복사

PHP 버그인가요? PHP에서 왜 이런 이상한 동작이 발생합니까?

분석하다

첫 번째 foreach 루프가 끝난 후에도 $item은 여전히 ​​배열의 마지막 요소인 $arr[2]를 참조합니다. 따라서 두 번째 루프를 시작할 때 루프를 통과할 때마다 $item 변수에 새 값이 할당됩니다. PHP에서는 메모리 공간이 참조되면 이를 변경하면 이 메모리 공간의 값이 직접 변경됩니다. $item이 변경되면 $arr[2] 값도 변경됩니다.

두 번째 루프에서는

루프를 처음 통과하면 $item과 $arr[2]의 값은 $arr[0], 즉 'foo'가 됩니다. 두 번째 루프에서는 $item과 $arr[2]의 값이 'bar'인 $arr[1]이 됩니다. 세 번째 루프에서는 $item 및 $arr[2]의 값이 'bar'인 $arr[2]가 됩니다(두 번째 루프에서는 $arr[2]의 값이 'baz'가 아니기 때문입니다). '바'가 됩니다.)

'baz'의 값은 실제로 두 번째 루프에서 손실됩니다.

번역 참고: 저는 참고문헌을 '인용문'은 물론이고 '인용문'으로 번역하는 걸 좋아하지 않습니다. 나는 누군가에게 참조를 설명할 때마다 참조는 별칭입니다라고 말합니다. 예를 들어, 귀하의 이름은 Wu Yichang(하하, 특이한 것은 아닙니다)이고 Ergouzi는 귀하의 별칭입니다. 좋은 형제와 좋은 친구 사이의 우정의 정신으로: “자, 에르구지, 이 100위안을 드리겠습니다.” 당신 - Wu Yichang - 100위안을 더 내고 똑같은 주머니를 가지고 집에 갑니다. @justjavac

디버그 출력

코드를 수정하여 루프의 실행 세부 사항을 디버깅하고 추적할 수 있습니다. $item의 값을 인쇄하고 $arr 배열을 재귀적으로 인쇄할 수 있습니다.

첫 번째 루프가 실행되면 다음과 같은 출력을 볼 수 있습니다.

  1. foo
  2. 배열( [0] => foo [1] => bar [2] => baz )
  3. bar
  4. 배열( [0] => foo [1] => bar [2] => baz )
  5. baz
  6. 배열( [0] => foo [1] => bar [2] => baz )
코드 복사

루프가 끝난 후 $item과 $arr[2]는 동일한 메모리 영역을 가리킵니다.

두 번째 루프가 실행되면 다음 출력이 표시됩니다.

  1. foo
  2. 배열( [0] => foo [1] => bar [2] => foo )
  3. bar
  4. 배열( [0] => foo [1] => bar [2] => bar )
  5. bar
  6. Array ( [0] => foo [1] => bar [2] => 바 )
코드 복사

이 루프에서는 $item에 새 값이 할당될 때마다 $arr[2]에도 $item과 동일한 값이 할당됩니다. 둘 다 여전히 동일한 메모리 공간을 가리키기 때문입니다( 번역 참고 사항: 원문은 $arr[3]으로 되어 있는데, 이는 원저자인 @justjavac)의 사무적인 오류로 의심됩니다. 루프가 배열의 세 번째 값에 도달하면 이전 두 루프에서 해당 값이 수정되었기 때문에 값 막대가 포함됩니다.

아직도 질문이 있습니다

내가 방금 빈 루프 foreach($arr as &$item){}를 실행했는데 루프 본문에서 아무 작업도 수행되지 않았다고 생각할 수도 있습니다. 배열 요소가 변경된 이유는 무엇입니까?

이 코드가

과 동일해야 한다고 생각할 수도 있습니다.
  1. for ($i = 0; $i < count($arr); $i ) {
  2. // 아무것도 하지 않음
  3. }
코드 복사

그렇지 않습니다. 코드는 다음과 동일해야 합니다.

  1. for ($i = 0; $i < count($arr); $i ) {
  2. $item = $arr[$i]
  3. }
코드 복사

즉, foreach 루프에서는 할당 작업 이 암시적이라는 점만 다릅니다. 할당 프로세스 중에 참조를 사용했기 때문에 첫 번째 루프에서 루프되는 배열 내부의 요소를 실수로 수정했습니다.

PHP


원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿