在PHP中有人可以解释克隆vs指针引用吗? [英] In PHP can someone explain cloning vs pointer reference?

查看:67
本文介绍了在PHP中有人可以解释克隆vs指针引用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我了解编程和对象,但是在PHP中,以下内容对我而言意义不大.

To begin with, I understand programming and objects, but the following doesn't make much sense to me in PHP.

在PHP中,我们使用&运算符,以获取对变量的引用.我理解引用是一种引用具有不同变量的相同事物"的方式.如果我说

In PHP we use the & operator to retrieve a reference to a variable. I understand a reference as being a way to refer to the same 'thing' with a different variable. If I say for example

$b = 1;
$a =& $b;
$a = 3;
echo $b;

将输出3,因为对$ a所做的更改与对$ b所做的更改相同.相反:

will output 3 because changes made to $a are the same as changes made to $b. Conversely:

$b = 1;
$a = $b;
$a = 3;
echo $b;

应输出1.

如果是这种情况,为什么必须使用clone关键字?在我看来,如果我设置

If this is the case, why is the clone keyword necessary? It seems to me that if I set

$obj_a = $obj_b,则对$ obj_a所做的更改不应影响$ obj_b, 相反$ obj_a =& $ obj_b应该指向同一个对象,因此对$ obj_a所做的更改会影响$ obj_b.

$obj_a = $obj_b then changes made to $obj_a should not affect $obj_b, conversely $obj_a =& $obj_b should be pointing to the same object so changes made to $obj_a affect $obj_b.

但是,在PHP中,即使在没有引用运算符($obj_a = $obj_b)的情况下,对$ obj_a的某些操作也确实会影响$ obj_b.今天,在使用DateTime对象工作时,这给我造成了一个令人沮丧的问题,而我最终通过基本完成的工作来解决了这个问题:

However it seems in PHP that certain operations on $obj_a DO affect $obj_b even if assigned without the reference operator ($obj_a = $obj_b). This caused a frustrating problem for me today while working with DateTime objects that I eventually fixed by doing basically:

$obj_a = clone $obj_b

但是我写的大多数php代码似乎不需要像在这种情况下那样的显式克隆,没有它就可以正常工作.这里发生了什么?为什么PHP必须这么笨拙?

But most of the php code I write doesn't seem to require explicit cloning like in this case and works just fine without it. What's going on here? And why does PHP have to be so clunky??

推荐答案

基本上,PHP中有两种工作变量的方法...

Basically, there are two ways variables work in PHP...

除对象外的所有内容:

  1. 分配是按值进行的(意味着如果您执行$a = $b,则会进行复制.
  2. 可以通过执行$a = &$b来实现引用(请注意,引用运算符对变量而不是赋值运算符进行操作,因为您可以在其他地方使用它)...
  3. 副本使用写时复制技术.因此,如果执行$a = $b,则没有该变量的内存副本.但是,如果您随后执行$a = 5;,则会复制该内存,然后将其覆盖.
  1. Assignment is by value (meaning a copy occurs if you do $a = $b.
  2. Reference can be achieved by doing $a = &$b (Note the reference operator operates upon the variable, not the assignment operator, since you can use it in other places)...
  3. Copies use a copy-on-write tehnique. So if you do $a = $b, there is no memory copy of the variable. But if you then do $a = 5;, the memory is copied then and overwritten.

对于对象:

  1. 分配是通过对象引用进行的.通过引用,它与普通变量实际上并不相同(我将在后面解释原因).
  2. 可以通过执行$a = clone $b来实现按值复制.
  3. 可以通过执行$a = &$b来实现引用,但是请注意,这与对象无关.您正在将$a变量绑定到$b变量.不管它是否是对象都没有关系.
  1. Assignment is by object reference. It's not really the same as normal variable by reference (I'll explain why later).
  2. Copy by value can be achieved by doing $a = clone $b.
  3. Reference can be achieved by doing $a = &$b, but beware that this has nothing to do with the object. You're binding the $a variable to the $b variable. It doesn't matter if it's an object or not.

那么,为什么没有真正引用对象的分配?如果您这样做会发生什么:

So, why is assignment for objects not really reference? What happens if you do:

$a = new stdclass();
$b = $a;
$a = 4;

什么是$b?嗯,它是stdclass ...这是因为它不是写对变量的引用,而是写对对象的引用

What's $b? Well, it's stdclass... That's because it's not writing a reference to the variable, but to the object...

$a = new stdclass();
$a->foo = 'bar';
$b = $a;
$b->foo = 'baz';

什么是$a->foo? baz.这是因为当您执行$b = $a时,您是在告诉PHP使用相同的对象实例(因此引用了对象).请注意,$a$b不是相同的变量,但是它们都引用相同的对象.

What's $a->foo? It's baz. That's because when you did $b = $a, you are telling PHP to use the same object instance (hence the object reference). Note that $a and $b are not the same variable, but they do both reference the same object.

一种思考方式是,将存储对象的所有变量都视为存储指向该对象的指针.因此,该对象位于其他地方.当您分配$a = $b其中$b是一个对象时,您要做的就是复制该指针.实际变量仍然不相交.但是,当您执行$a = &$b时,您将在$a内部存储一个指向$b的指针.现在,当您操作$a时,它会将指针链级联到基础对象.当使用clone运算符时,您要告诉PHP复制现有对象,并创建一个具有相同状态的新对象.因此clone实际上只是对变量进行按值复制...

One way of thinking about it, is to think of all variables which store an object as storing the pointer to that object. So the object lives somewhere else. When you assign $a = $b where $b is an object, all you're doing is copying that pointer. The actual variables are still disjoint. But when you do $a = &$b, you're storing a pointer to $b inside of $a. Now, when you manipulate $a it cascades the pointer chain to the base object. When you use the clone operator, you're telling PHP to copy the existing object, and create a new one with the same state... So clone really just does a by-value copy of the varaible...

因此,如果您注意到了,我说过该对象未存储在实际变量中.它存储在其他位置,并且变量中只存储了一个指针.因此,这意味着您可以(并且经常有)指向同一实例的多个变量.因此,内部对象表示形式包含refcount(仅是指向它的变量数量的计数).当对象的引用计数降至0(意味着指向该对象的所有变量都超出范围,或更改为其他变量)时,将对其进行垃圾回收(因为它不再可访问)...

So if you noticed, I said the object is not stored in an actual variable. It's stored somewhere else and nothing but a pointer is stored in the variable. So this means that you can have (and often do have) multiple variables pointing to the same instance. For this reason, the internal object representation contains a refcount (Simply a count of the number of variables pointing to it). When an object's refcount drops to 0 (meaning that all the variables pointing to it either go out of scope, or are changed to somethign else) it is garbaged collected (as it is no longer accessable)...

您可以在文档中的引用和PHP上阅读更多内容...

免责声明:其中一些可能是某些概念的过度简化或模糊化.我的目的只是作为它们工作方式的指南,而不是内部发生的确切故障...

Disclaimer: Some of this may be oversimplification or blurring of certain concepts. I intended this only to be a guide to how they work, and not an exact breakdown of what goes on internally...

哦,至于这是笨拙的",我认为不是.我认为这真的很有用.否则,您将在各处传递变量引用.当应用程序一个部分中的变量影响应用程序另一部分中的另一个变量时,这可能会产生一些非常有趣的错误.这不是因为它已通过,而是因为在沿线的某个地方进行了引用.

Oh, and as for this being "clunky", I don't think it is. I think it is really useful. Otherwise you'd have variable references being passed around all over the place. And that can yield some really interesting bugs when a variable in one part of an application affects another variable in another part of the app. And not because it's passed, but because a reference was made somewhere along the line.

通常,我不会使用太多的变量引用.我很少发现他们有诚实的需求.但是我一直都在使用对象引用.我使用它们太多了,我很高兴它们是默认值.否则,我需要编写一些运算符(由于&表示变量引用,因此需要另一个表示对象引用).考虑到我很少使用clone,我想说99.9%的用例应使用对象引用(这样可使运算符用于频率较低的情况)...

In general, I don't use variable references that much. It's rare that I find an honest need for them. But I do use object references all the time. I use them so much, that I'm happy that they are the default. Otherwise I'd need to write some operator (since & denotes a variable reference, there'd need to be another to denote an object reference). And considering that I rarely use clone, I'd say that 99.9% of use cases should use object references (so make the operator be used for the lower frequency cases)...

JMHO

我还创建了一个解释这些差异的视频.在YouTube上中查看.

I've also created a video explaining these differences. Check it out on YouTube.

这篇关于在PHP中有人可以解释克隆vs指针引用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆