前兩天有人在羣裏說了一個關於 new
和 stdClass
的問題,具體表現以下:php
<?php $a = new stdClass; $b = new $a; var_dump($a, $b);
這段代碼是能夠正確運行的,而且 $a
和 $b
是兩個不一樣的空對象。即便在 new $a
以前給 $a
添加屬性並賦值,$b
也始終是一個的空對象。測試
因此問題就是:爲何空對象還能夠跟在 new
後面,stdClass
有什麼特殊的地方嗎?code
其實主要稍加驗證就能知道,其實這和 stdClass
並無什麼關係,徹底是 new
的行爲決定的,好比在 psysh 上作一下簡單的測試:對象
>>> $a = new Reflection; => Reflection {#174} >>> $b = new $a; => Reflection {#177}
這裏我是 new 了一個 Reflection
類的實例,和 stdClass
的表現沒有區別。固然也能夠自定義一個類:get
>>> class Test { public $foo = 1; } => null >>> $a = new Test => Test {#178 +foo: 1, } >>> $a->foo = 2; => 2 >>> $b = new $a; => Test {#180 +foo: 1, }
從這個例子中咱們能夠清楚的看到,改變 $a
的屬性對 $b
沒有任何影響(到這裏也能夠順便思考一下 PHP 的一個關鍵字:clone
)。源碼
既然已經知道了表現,也能夠獲得結論:經過一個類的對象 new
出一個新對象等同於 new
原對象的類。io
那麼 PHP 是什麼樣的實現形成了這種表現呢?仍是從源碼入手來解析這個問題。class
其實從源碼中,咱們能夠直奔 zend_vm_def.h
中找到答案,在關於 ZEND_FETCH_CLASS
這個 opcode 的解釋中,咱們能夠看到如下內容:文件
ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMPVAR|UNUSED|CV) { ... if (OP2_TYPE == IS_CONST) { ... } else if (Z_TYPE_P(class_name) == IS_OBJECT) { Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name); } ... ... }
去掉一些干擾的上下文,上面的內容很清晰的呈現出一個解釋:若是取到的 class_name
是一個對象,則經過 Z_OBJCE_P
的宏找到它的類。因此上面的表現解釋起來就很容易了。思考
這自己是一個很簡單的問題,不用往復雜了去想。若是想知道具體的 new
的實現,能夠到 zend_compile.c
文件中去查看 zend_compile_new
的實現。