PHP 的 new 的小問題的探究

來源:互聯網
上載者:User

問題起因

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

<?php$a = new stdClass;$b = new $a;var_dump($a, $b);

這段代碼是可以正確啟動並執行,並且 $a 和 $b 是兩個不同的Null 物件。即使在 new $a 之前給 $a 添加屬性並賦值,$b 也始終是一個的Null 物件。

所以問題就是:為什麼Null 物件還可以跟在 new 後面,stdClass 有什麼特殊的地方嗎?

實際表現

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

>>> $a = new Reflection;=> Reflection {#174}>>> $b = new $a;=> Reflection {#177}

這裡我是 new 了一個 Reflection 類的執行個體,和 stdClass 的表現沒有區別。當然也可以自訂一個類:

>>> 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 原對象的類。

原因

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

其實從源碼中,我們可以直奔 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 的實現。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.