PHP 对象赋值与克隆

2022-08-30 16:05:36

我知道这在php文档中有所涉及,但我对这个问题感到困惑。

来自 php 文档:

$instance = new SimpleClass();
$assigned   =  $instance;
$reference  =& $instance;
$instance->var = '$assigned will have this value';
$instance = null; // $instance and $reference become null
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>

上面的示例将输出:

NULL
NULL
object(SimpleClass)#1 (1) {
["var"]=>
 string(30) "$assigned will have this value"
}

好吧,所以我看到在原始对象()被分配给中幸存下来,所以显然不是引用,而是$instance的副本。$assigned$instancenull$assigned

那么两者之间有什么区别呢?

 $assigned = $instance 

 $assigned = clone $instance

答案 1

对象是内存中的抽象数据。变量始终在内存中保存对此数据的引用。想象一下,在内存中的某个地方创建一个对象实例,为其分配一些id,然后现在将其作为对此对象的引用。通过引用将此引用分配给其他变量,或者通常与任何其他值的工作方式相同。许多变量可以保存此引用的副本,但都指向同一对象。$foo = new BarBar#42$foo#42

clone显式创建对象本身的副本,而不仅仅是指向该对象的引用的副本。

$foo = new Bar;   // $foo holds a reference to an instance of Bar
$bar = $foo;      // $bar holds a copy of the reference to the instance of Bar
$baz =& $foo;     // $baz references the same reference to the instance of Bar as $foo

只是不要将“引用”与对象标识符中的“引用”混淆。=&

$blarg = clone $foo;  // the instance of Bar that $foo referenced was copied
                      // into a new instance of Bar and $blarg now holds a reference
                      // to that new instance

答案 2

区别

 $assigned = $instance 

 $assigned = clone $instance

在第一种情况下,您分配了现有对象的引用,在第二种情况下,您创建了一个新对象并将其分配给变量。

此外,当您使用 clone 关键字时,您可以使用魔术方法__clone(),这样可以更好地控制对象克隆。从 php 手册:

克隆完成后,如果定义了__clone() 方法,则将调用新创建对象的 __clone() 方法,以允许需要更改的任何必要属性。

手册

PHP 引用是一个别名,它允许两个不同的变量写入相同的值。从 PHP 5 开始,对象变量不再包含对象本身作为值。它只包含一个对象标识符,该标识符允许对象访问器查找实际对象。当一个对象通过参数发送,返回或分配给另一个变量时,不同的变量不是别名:它们保存指向同一对象的标识符的副本。

让我举一个活生生的例子

$dateA = new \Datetime('2017-04-04');

$dateB = $dateA; // $dateB references exactly the same object as $dateA

$dateB->modify('+1 day');

var_dump($dateA->format('Y-m-d')); //string(10) "2017-04-05" 
var_dump($dateB->format('Y-m-d')); //string(10) "2017-04-05"


// $dateA is still modified by the code above so it has 2017-04-05
$dateC = clone $dateA; // we clone $dateA so it's a new object

$dateC->modify('+1 day');

var_dump($dateA->format('Y-m-d')); // string(10) "2017-04-05" 
var_dump($dateC->format('Y-m-d')); // string(10) "2017-04-06"

日期时间的旁注 我建议使用日期时间不可变而不是日期时间

编辑:内部类型

// create 2 integer variables $a and $b

$a = 1;
$b = 1;

// create a new $c variable and assign the *value* of $a to that variable
$c = $a;

// create a new $d variable and assign a reference to $b variable
$d = &$b;

// increment $b, $c and $d variables
$b++; 
$c++;
$d++;

echo $a; // 1
echo $b; // 3
echo $c; // 2
echo $d; // 3

因为$d引用$b当我们增加其值时,它也将更改$b的值。

内部对象(如字符串,int,float等)之间的区别在于它们按值传递,而对象默认通过引用传递。

注意:不能对内部对象使用克隆。


推荐