假定的数组副本上的嵌套foreach循环改变了原始数组的内部指针

时间:2017-04-19 13:47:33

标签: php oop foreach copy array-key

使用PHP 5.5.9并给出此示例测试类:

MyDbContext

并执行此示例测试:

class Test
  implements Iterator
{
  private $ar = [ 1, 2, 3 ];

  public function toArray() {
    return $this->ar;
  }

  public function rewind() {
    reset( $this->ar );
  }

  public function valid() {
    return !is_null( $this->key() );
  }

  public function key() {
    return key( $this->ar );
  }

  public function current() {
    return current( $this->ar );
  }

  public function next() {
    next( $this->ar );
  }
}

我得到以下结果:

$t = new Test;
foreach( $t as $key => $value ) {
  echo "orig: $key: $value\n";

  // work on the immediate method result
  foreach( $t->toArray() as $copyKey => $copyValue ) {
    echo "  copy: $copyKey: $copyValue\n";
  }

  echo "----\n";
}

当我期望orig: 0: 1 copy: 0: 1 copy: 1: 2 copy: 2: 3 ---- 时,内部foreach循环似乎正在处理对$ar的内部成员Test的引用并推进其内部指针给我一份$t->toArray()的内部成员$ar的副本。

由于我的理解是PHP总是复制数组,当从方法返回时,肯定是,我期望得到以下结果:

Test

当我在内部orig: 0: 1 copy: 0: 1 copy: 1: 2 copy: 2: 3 ---- orig: 1: 2 copy: 0: 1 copy: 1: 2 copy: 2: 3 ---- orig: 2: 3 copy: 0: 1 copy: 1: 2 copy: 2: 3 ---- 循环之前制作数组的显式副本时,使用:

foreach

或者将// store method result in variable first $a = $t->toArray(); foreach( $a as $copyKey => $copyValue ) { /* etc. */ } 方法更改为:

toArray()

获得预期的结果。

这里发生了什么?这是预期的行为吗?我在这里忽略了一些重要的东西吗?

显然,这种行为在PHP 7.0.0中消失了:

https://3v4l.org/l96fW

1 个答案:

答案 0 :(得分:0)

在v5.x中取消引用数组:

$t = new Test;
foreach( $t as $key => $value ) {
    echo "orig: $key: $value\n";

    $a = $t->toArray(); // copy of array happens under `=` sign
    foreach( $a as $copyKey => $copyValue ) {
        echo "  copy: $copyKey: $copyValue\n";
    }

    echo "----\n";
}