我知道这是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"
}
好的,所以我看到$assigned
幸存原始对象($instance
)被分配到null
,所以显然$assigned
不是引用但是$ instance的副本。
那么
之间有什么区别 $assigned = $instance
和
$assigned = clone $instance
答案 0 :(得分:18)
对象是内存中的抽象数据。变量始终将引用保存到内存中的此数据。想象一下,$foo = new Bar
在内存中的某处创建了Bar
的对象实例,为其分配了一些ID #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
答案 1 :(得分:8)
之间的区别
$assigned = $instance
和
$assigned = clone $instance
是在第一种情况下,您分配已存在对象的引用,在第二种情况下,您创建一个新对象并将其分配给变量。
此外,当您使用 clone 关键字时,您可以使用magic方法__clone(),它可以更好地控制对象克隆。来自php手册:
克隆完成后,如果定义了__clone()方法,则将调用新创建的对象的__clone()方法,以允许任何需要更改的必要属性。
来自manual:
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"
//日期时间的侧边注释我建议使用DatetimeImmutable而不是Datetime
答案 2 :(得分:2)
$assigned = $instance
上面会将$ instance分配给$ assigned,最基本的赋值。
$assigned = clone $instance
这是对象克隆。将对象$ instance的副本分配给$ assigned。
没有克隆,$ assigned和$ instance具有相同的对象ID,这意味着它们指向同一个对象。
答案 3 :(得分:2)
PHP不像管理其他数据类型那样管理对象。字符串(或整数,布尔值,浮点数或数组)直接存储在变量中。当变量的值分配给另一个变量时,该值将被复制 1 到新变量中。
例如:
$x = array('a');
$y = $x;
// $x and $y are different and unrelated variables; they do not share anything
$y[] = 'b';
print_r($y);
// Array
// (
// [0] => a
// [1] => b
// )
print_r($x);
// Array
// (
// [0] => a
// )
另一方面,对象由PHP使用唯一标识符处理。将对象分配给变量时,标识符存储在变量中,而不是实际对象中。
当变量的值分配给另一个变量时,将复制标识符,而不是对象本身。这使得两个变量指向同一个对象。
使用您的示例,变量$instance
和$assigned
的值相等,它们都包含同一对象的标识符。另一方面,$reference
是一个引用,即变量$assigned
的别名(不同的名称)。这就是语句$instance = null;
清除变量$reference
和$assigned
的内容的原因,但它不会影响变量$instance
以及其标识符存储在其中的对象它
在将$reference
设置为null
之前,可以使用$instance
,$assigned
或reference
中的任何一个来访问在SimpleClass
上创建的$instance = new SimpleClass();
$assigned = $instance;
$instance->var = '$assigned will have this value';
echo($instance->var);
// It prints:
// $assigned will have this value
// $assigned is also modified because it is the same object
echo($assigned->var);
// It prints:
// $assigned will have this value
对象你的例子的第一行。 F.e:
$assigned = clone $instance
在文档中阅读有关PHP objects and references的更多信息。
$assigned = clone $instance;
时会发生什么? clone
operator创建其操作数的副本。它创建一个新对象,并通过将原始对象的属性值分配给它们来初始化其所有属性。这意味着如果克隆对象包含对象作为属性,则通过简单赋值而不是通过克隆来复制这些属性。 2
$assigned
在此声明之后,$instance
包含的值与$instance
不同,因为它们现在存储不同对象的ID。作为不同的对象,$assigned
的更改不再影响$instance = new SimpleClass();
$instance->var = '$instance has this value';
$assigned = clone $instance;
echo($assigned->var);
// It prints:
// $instance has this value
$assigned->var = '$assigned has a different value';
echo($assigned->var);
// It prints:
// $assigned has a different value
// $instance is not modified
echo($instance->var);
// It prints:
// $instance has this value
。
__clone()
1 这不完全正确。出于优化目的,在修改数组(写入时复制)之前不会复制数组。但是,这是一个实现细节,为了讨论的目的,可以考虑除了对象在分配给新变量时复制的所有值。
2 这也被称为"浅"克隆。为了得到一个深刻的" clone(一个不与原始文件共享任何内容的真实副本),具有对象作为属性的克隆对象的类必须实现__clone()
魔术方法并克隆原始对象的属性。此外,这些属性的类必须实现dplyr
等等。
答案 4 :(得分:1)
答案 5 :(得分:0)
保持简短&这里很简单:
此处$reference
类似于对象$instance
的别名。而最初$assignment
和$reference
指向对象$instance
的数据空间。
当$instance
指向的值发生变化时,它会随处更改。
但在$instance = null
时,我们在这里$instance
指向null
,因为$reference
是别名所以:
$ reference - > $ instance - >空....
$assignment
仍保留指向由$instance
创建的对象的数据空间的指针,但现在$instance
不再需要相同的内容。
答案 6 :(得分:0)
这是克隆和分配之间的区别:
class MyClass {
public $color;
public $amount;
}
$obj = new MyClass();
$obj->color = 'red';
$obj->amount = 5;
$copy = clone $obj;
$assign = $obj;
$obj->amount = 7;
print_r($copy);//it will print : MyClass Object ( [color] => red [amount] => 5 )
print_r($assign);//it will print : MyClass Object ( [color] => red [amount] => 7 )
答案 7 :(得分:-2)
它只是创建一个全新的对象,它保留了被复制对象的属性。它执行深层复制:
$assigned = $instance;
将对象从一个对象复制到另一个时,它会生成一个浅的副本:
$assigned = clone $instance;