Bug #75158 [Opn->Nab]: Cloning objects whith members that hold references to other members

From: Date: Wed, 06 Sep 2017 09:04:53 +0000
Subject: Bug #75158 [Opn->Nab]: Cloning objects whith members that hold references to other members
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-210970@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=75158&edit=1 ID: 75158 Updated by: danack@php.net Reported by: krulis at ksi dot mff dot cuni dot cz Summary: Cloning objects whith members that hold references to other members -Status: Open +Status: Not a bug Type: Bug Package: Class/Object related Operating System: all PHP Version: 7.1.9 Block user comment: N Private report: N New Comment: Closing as not a bug, because I think that's how references 'work'. Previous Comments: ------------------------------------------------------------------------ [2017-09-05 17:15:20] danack@php.net I don't think this is a bug......it's just that references are really, really, confusing. For the line "$this->ref =& $this->data;" this does not create a variable called 'ref' that is a reference to the 'real' variable called 'data'. Instead it moves the variable elsewhere and sets both 'data' and 'ref' to be a reference to that variable. This in unlike other programming languages that use pointers. In those, creating a point to a value does not affect how the original value is stored. But in PHP, creating a reference does make the original property become a reference. A workaround for this is to explicitly copy the values, destroy the variable with unset() to remove the fact that it's a reference to another variable, and then copy the values over. class Foo { public $data; public $ref; public function __construct() { $this->data = []; $this->ref = &$this->data; } public function __clone() { $values = (array)$this->data; unset($this->data); $this->data = [$values]; $this->ref = &$this->data; } } $o = new Foo(); $o->data[] = 1; $c = clone($o); $o->data[] = 42; var_dump($c->data); Or you could just not use references. ------------------------------------------------------------------------ [2017-09-05 15:27:26] krulis at ksi dot mff dot cuni dot cz Description: ------------ When I have an object and one member variable is a reference to another member variable, clone of such object is not correctly constructed. In the test script, you can see Foo class with two members: $data and $ref. $ref is set to be a reference to $data of the same object. When object of foo is cloned. The clone's $data is in fact reference to original object's $data. In other words, clone should in fact do $c->data = $o->data (shallow copy by = operator), but instead, it seems like $c->data =& $o->data. Note that the references are in fact not used, and when they are removed (line in the constructor is commented), it starts to work correctly again. I have also tested integer values in $data (beside arrays) and they work all the same. This behavior was observed on Windows 7.1.9 and Linux 5.6.26. A similar problem was described in #66040, but I am not sure, whether they are connected or not. Test script: --------------- <?php class Foo { public $data = []; public $ref; public function __construct() { $this->ref =& $this->data; } } $o = new Foo(); $c = clone($o); $o->data[] = 42; var_dump($c->data); // writes out an array with one item (42), even though the array should be empty Expected result: ---------------- I would expect that $c->data === [] at the end. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=75158&edit=1

« previous php.bugs (#210970) next »