PHP 的 new 的小問題的探究

高洛峰
發布: 2016-11-22 09:17:14
原創
1054 人瀏覽過

問題起因

前兩天有人在群組裡說了一個關於 new 和 stdClass 的問題,具體表現如下:

<?php
$a = new stdClass;
$b = new $a;
var_dump($a, $b);
登入後複製

這段程式碼是可以正確運作的,並且 $a 和 $b 對象。即使在 new $a 之前為 $a 新增屬性並賦值,$b 也始終是一個的空物件。

所以問題就是:為什麼空對象還可以跟在 new 後面,stdClass 有什麼特別的地方嗎?

實際表現

其實主要稍加驗證就能知道,其實這和 stdClass 並沒有什麼關係,完全是 new 的行為決定的,例如在 psysh 上做一下簡單的測試:

這裡reee

我是new 了一個 Reflection 類別的實例,和 stdClass 的表現沒有差別。當然也可以自訂一個類別:

>>> $a = new Reflection;
=> Reflection {#174}
>>> $b = new $a;
=> Reflection {#177}
登入後複製

從這個例子中我們可以清楚的看到,改變 $a 的屬性對 $b 沒有任何影響(到這裡也可以順便思考一下 PHP 的一個關鍵字:clone)。

既然已經知道了表現,也可以得到結論:透過一個類別的物件 new 出一個新物件等同於 new 原物件的類別。

原因

那麼 PHP 是什麼樣的實現造成了這種表現呢?還是從源碼入手來解析這個問題。

其實從原始碼中,我們可以直奔 zend_vm_def.h 中找到答案,在關於 ZEND_FETCH_CLASS 這個opcode 的解釋中,我們可以看到以下內容:

>>> class Test { public $foo = 1; }
=> null
>>> $a = new Test
=> Test {#178
     +foo: 1,
   }
>>> $a->foo = 2;
=> 2
>>> $b = new $a;
=> Test {#180
     +foo: 1,
   }
登入後複製

去掉一些幹擾的上下文,上面的內容很清晰的呈現出一個解釋:如果取到的 class_name 是一個對象,則透過 Z_OBJCE_P的巨集找到它的類別。所以上面的表現解釋起來就很容易了。

這本身是一個很簡單的問題,不用往複雜了去想。如果想知道特定的 new 的實現,可以到 zend_compile.c 檔案中去查看 zend_compile_new 的實作。


相關標籤:
php
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!