【问题标题】:Why are my PHP objects passed by reference为什么我的 PHP 对象是通过引用传递的
【发布时间】:2016-12-09 19:26:12
【问题描述】:

我看到一些与 PHP 中的引用/赋值相关的令人困惑的行为...

private function doSomething($things)
{
    foreach ($things as $thing) {
        echo $thing->property; // 'foobar'
        $copyThing = $thing;
        unset($copyThing->property);
        echo $thing->property; // undefined

我希望在通过引用传递变量时会出现这种行为 (&$thing),但我不想在这里这样做,而且它似乎无论如何都会发生。我错过了什么?

【问题讨论】:

  • foreach 循环中的对象总是通过引用传递
  • $thing 已经是 $things 在 foreach 循环中的传递引用
  • @MM 哇!在任何最新版本的 PHP 中,该默认值是否发生了变化?我发誓我记得必须使用 &$var 来公开通过引用。
  • 如果它是一个对象,那么不是.... 因为持有对象的变量总是一个指针
  • 你需要clone你的对象,例如:foreach ($things as $thing) { $copyThing = clone $thing; unset($copyThing->property); }

标签: php pass-by-reference variable-assignment


【解决方案1】:

只是解释我的评论:

foreach 循环中的对象总是通过引用传递

当您对对象数组使用 foreach 循环时,您在循环内使用的变量是指向该对象的指针,因此它可以作为参考,循环内对象的任何更改都是对象的更改外部。 这是因为:

对象总是通过引用传递(@user3137702 引用)

详细官方解释here.


当您复制和取消设置变量时:

$copyThing = $thing;
unset($copyThing->property);

您正在创建另一个指针并取消设置它,因此原始值已消失。事实上,由于 foreach 循环也使用指针,$things 数组也会受到影响。

检查ideone(注意 vardump ['a' 属性消失的地方],因为输出与您得到的相同)


我不知道它在哪个版本中更改,如果有的话,因为它看起来像默认对象/指针行为


作为一种解决方法(一些想法):

  1. 复制您的初始数组
  2. 使用clone:$x = clone($obj);(只要默认的复制构造函数适用于您的对象)

【讨论】:

  • 我会将其修改为简单地说“对象总是通过引用传递”,因为这种行为实际上与 foreach 循环没有任何关系。
  • 啊哈!我现在明白了。我最初误解它是关于所有 foreach 循环......但现在我明白它是对象独有的。如果我构造完全相同的示例,但不是 unseting 对象属性,而是 unset 数组中的键,它会被引用,这是否正确?
  • 是的,正确的。您将取消设置副本,只是因为:ideone
  • @M.M 有没有办法防止这种默认行为?换句话说,有没有一种方法可以只复制对象而不影响原始对象?
  • @emersonthis 正如我在答案的 workaround 部分中所说,您可以使用 clone 将对象复制到另一个变量(另一个内存位置,因此会有一个新的指针)
猜你喜欢
  • 2015-06-18
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 2016-03-31
  • 2012-06-24
  • 1970-01-01
  • 2013-05-22
  • 1970-01-01
相关资源
最近更新 更多