ホームページ  >  記事  >  バックエンド開発  >  PHP の新しい機能に関する小さな問題の調査

PHP の新しい機能に関する小さな問題の調査

高洛峰
高洛峰オリジナル
2016-11-22 09:17:141097ブラウズ

問題の原因

2 日前にグループで new と stdClass について質問した人がいます。具体的なパフォーマンスは次のとおりです:

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

このコードは正しく実行でき、$a と $b は 2 つの異なるオブジェクトです。 。新しい $a の前に属性が追加され、値が $a に割り当てられた場合でも、 $b は常に空のオブジェクトです。

それでは、なぜ空のオブジェクトが new の後に続くことができるのでしょうか? stdClass には何か特別なものがあるのでしょうか?

実際のパフォーマンス

実際、これは stdClass とはまったく関係なく、たとえば psysh で簡単なテストを実行してください。

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

私はここが初めてです。 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 の説明で次のことがわかります:

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 の実装を表示できます。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。