Home > Backend Development > PHP Tutorial > Strange problems caused by 'references' in PHP loops

Strange problems caused by 'references' in PHP loops

WBOY
Release: 2016-07-25 08:46:29
Original
994 people have browsed it

This article is compiled from an article on the stackoverflow website Strange behavior after loop by reference - Is this a PHP bug? —— Using references inside a PHP loop causes very strange behavior - is this a PHP bug?

question

While I was writing a simple PHP script, something very strange happened. The following is my code. In order to express what I mean clearly, I deliberately removed some unnecessary code:

  1. $arr = array("foo",
  2. "bar",
  3. "baz");
  4. foreach ($arr as &$item) { /* do nothing by reference */ }
  5. print_r($arr);
  6. foreach ($arr as $item) { /* do nothing by value */ }
  7. print_r($arr); // $arr has changed....why?
Copy code

The output is as follows:

  1. Array
  2. (
  3. [0] => foo
  4. [1] => bar
  5. [2] => baz
  6. )
  7. Array
  8. (
  9. [0] => foo
  10. [1] = > bar
  11. [2] => bar // Error occurred?
  12. )
Copy code

Is this a bug in PHP? Why does such weird behavior happen in PHP?

parse

After the first foreach loop ends, $item still references the last element of the array, which is $arr[2]. Therefore, when starting the second loop, the $item variable will be assigned a new value each time through the loop. In php, if a memory space is referenced, then when you change it, the value of this memory space is directly changed. When $item is changed, the value of $arr[2] is also changed.

So, in the second loop:

The first time through the loop, the values ​​of $item and $arr[2] become $arr[0], which is 'foo'. In the second loop, the values ​​of $item and $arr[2] become $arr[1], which is 'bar'. In the third loop, the values ​​of $item and $arr[2] become $arr[2], which is 'bar' (the value of $arr[2] is not 'baz', because in the second loop it becomes 'bar').

The value of 'baz' is actually lost in the second loop.

Translation Note: I don’t like to translate reference into “quote”, of course, let alone “reference”. Every time I explain reference to someone, I tell them: reference is alias. For example, your name is Wu Yichang (haha, nothing unusual), and Ergouzi is your alias. In the spirit of the friendship between good brothers and good friends: “Come on, Ergouzi, I’ll give you these 100 yuan.” You - Wu Yichang - go home with exactly the same pocket, 100 yuan extra. @justjavac

debug output

We can modify the code to debug and trace the execution details of the loop. We can print the value of $item and recursively print the array $arr.

When the first loop runs, we can see output like this:

  1. foo
  2. Array ( [0] => foo [1] => bar [2] => baz )
  3. bar
  4. Array ( [0] => foo [1] => bar [2] => baz )
  5. baz
  6. Array ( [0] => foo [1] => bar [2] => baz )
Copy code

After the loop ends, $item and $arr[2] point to the same memory area.

When the second loop runs, we see this output:

  1. foo
  2. Array ( [0] => foo [1] => bar [2] => foo )
  3. bar
  4. Array ( [0] => foo [1] => bar [2] => bar )
  5. bar
  6. Array ( [0] => foo [1] => bar [2] => bar )
Copy code

In this loop, please note that each time $item is assigned a new value, $arr[2] will also be assigned the same value as $item, because they both still point to the same memory space (Annotation: The original text reads $arr[3], which is suspected to be a typo by the original author @justjavac). When the loop reaches the third value in the array, it contains the value bar because its value was modified during the previous two loops.

Still have questions

Maybe you think that I just executed an empty loop foreach ($arr as &$item){} and nothing was done in the loop body. Why did the array elements change?

Maybe you think this code should be equivalent to

  1. for ($i = 0; $i < count($arr); $i++) {
  2. // do nothing
  3. }
Copy code

In fact, that’s not right. The code should be equivalent to:

  1. for ($i = 0; $i < count($arr); $i++) {
  2. $item = $arr[$i];
  3. }
Copy code

In other words, In the foreach loop, an assignment operation is implicit. The only difference is that During the assignment process, we used references, so in the first loop, we inadvertently modified the elements inside the array being looped.

PHP


source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template