0

我有这个 php 代码

$a = array('one');

$b[0] = &$a[0];

$c = $a;

$b[0] = 'three';

$a = array('two');

var_dump($a); echo '<br/>';

var_dump($b); echo '<br/>';

var_dump($c); echo '<br/>';

哪个输出这个->

array(1) { [0]=> string(3) "two" }

array(1) { [0]=> &string(5) "three" }

array(1) { [0]=> &string(5) "three" }

$b 和 $a 指向相同的值,但 $c 不应该指向相同的值,它应该有自己的值副本。然后,当我将 $b 的值更改为 3 时,我不明白为什么 $c 的值也会更改。我怎样才能防止这种情况?另外,当我将$a 的值更改为'two' 时,为什么$b 也不会更改为'two'?

提前致谢。

4

4 回答 4

3

你的问题是:

$b[0] = &$a[0];

这引用了数组的第一个元素。从var_dump()输出可以看出&string(5)

所以$b不引用整个数组,只引用第一个元素。

要引用整个数组,您需要执行以下操作:

$b = &$a;

这样做可以如您所愿:

// $a
array(1) {
  [0]=>
  string(3) "two"
}
// $b
array(1) {
  [0]=>
  string(3) "two"
}
// $c
array(1) {
  [0]=>
  string(3) "one"
}

阅读更多关于PHP 中的数组

于 2013-08-23T15:33:29.697 回答
2

这是一步一步的解释:

$a = array('one');
$b[0] = &$a[0];

$b现在是一个数组,它的第一个元素引用$a. 在符号表中,$b[0]$a[0]指向相同的底层 zval。

$c = $a;

$c现在引用$a,但尚未制作副本(写时复制语义)。它看起来很像这样:

$c ----/----> $a             $b
(0: 'one')    0: 'one' <---- 0: 'one'

下一个声明:

$b[0] = 'three';

$a[0]也会更新,反过来也会更新$c[0],因为$a它本身并没有改变。现在看起来像;

$c ----/----> $a               $b
(0: 'three')  0: 'three' <---- 0: 'three'

下一个声明:

$a = array('two');

$a$c和断开连接$a[0]$b[0]

$c          $a        $b
0: 'three'  0: 'two'  0: 'three'

预防

为了防止这种行为,您需要引用整个数组而不是一个元素:

$b = &$a;

通过这样做,$b现在$a引用相同的 zval(数组本身),因此所做的任何更改都会断开它与$c.

不过,我会考虑语言的这些边缘情况,如果您不需要,我建议不要使用引用。

于 2013-08-23T15:33:34.653 回答
1

重要的是要了解在通过引用与值分配时您在做什么。让我们一行一行地走。

$a = array('one');

创建的内存位置,我们称之为 M1。$a 指向 M1,在 M1 中我们有一个包含 1 个条目的数组,我们称之为 M1-A1。

$b[0] = &$a[0];

现在我们正在做的是将 $b[0] 指向 M1-A1。请记住,$a[0] 也指向 M1-A1,因此两者都指向内存的这个特定部分。请记住,$b 本身有它自己的内存位置 M2,但在 M2 内我们指向 M1-A1(即 M2-A1 指向 M1-A1)。

$c = $a;

由于我们不是通过引用分配,所以我们得到的是一个新的内存位置,我们称之为 M3,但在 M3 中有一个数组,第一个条目仍然指向 M1-A1。

所以现在我们有了 M1、M2、M3,在 M2 和 M3 中有一个数组条目指向 M1-A1。

$b[0] = 'three';

由于 $b[0] 实际上指向 M1-A1,我们实际上是在更改 M1-A1 内存点的值。所以任何引用 M1-A1 位置的东西也会看到这个值发生变化。

$a = array('two');

此时我们正在完全改变 $a 的内存位置。最初它是 M1,现在我们正在创建一个新的内存位置,M4。没有其他东西指向 M4 和 M4-A1 不指向 M1-A1。

因此,当我们执行 var dump 时,我们会得到您提到的值。

我可能让这更令人困惑,但试着在纸上画出来,它会很清楚。了解所有内容都存储在内存中,变量只是指向内存位置。一旦你理解了这个原则,它就会全部到位。

于 2013-08-23T15:52:55.500 回答
-1

它们都引用内存中的同一个数组对象

于 2013-08-23T15:28:41.620 回答