Heim Backend-Entwicklung PHP-Tutorial 浅析PHP原理之变量分离/引用(Variables Separation)_php技巧

浅析PHP原理之变量分离/引用(Variables Separation)_php技巧

May 17, 2016 am 08:56 AM
分离 变量 引用

首先我们回顾一下zval的结构:

复制代码 代码如下:

struct _zval_struct {
        /* Variable information */
        zvalue_value value; /* value */
        zend_uint refcount;
        zend_uchar type; /* active type */
        zend_uchar is_ref;
};

其中的refcount和is_ref字段我们一直都没有介绍过,我们知道PHP是一个长时间运行的服务器端的脚本解释器。那么对于它来说,效率和资源占用率是一个很重要的衡量标准,也就是说,PHP必须尽量介绍内存占用率,考虑下面这段代码:
复制代码 代码如下:

   $var = "laruence";
   $var_dup = $var;
   unset($var);
?>

第一行代码创建了一个字符串变量,申请了一个大小为9字节的内存,保存了字符串”laruence”和一个NULL(/0)的结尾。
第二行定义了一个新的字符串变量,并将变量var的值”复制”给这个新的变量。
第三行unset了变量var
这样的代码在我们平时的脚本中是很常见的,如果PHP对于每一个变量赋值都重新分配内存,copy数据的话,那么上面的这段代码公要申请18个字节的内存空间,而我们也很容易的看出来,上面的代码其实根本没有必要申请俩份空间,呵呵,PHP的开发者也看出来了:
我们之前讲过,PHP中的变量是用一个存储在symbol_table中的符号名,对应一个zval来实现的,比如对于上面的第一行代码,会在symbol_table中存储一个值”var”, 对应的有一个指针指向一个zval结构,变量值”laruence”保存在这个zval中,所以不难想象,对于上面的代码来说,我们完全可以让”var”和”var_dup”对应的指针都指向同一个zval就可以了。
PHP也是这样做的,这个时候就需要介绍我们之前一直没有介绍过的zval结构中的refcount字段了。
refcount,顾名思义,记录了当前的zval被引用的计数。
比如对于代码:
复制代码 代码如下:

   $var = 1;
   $var_dup = $var;
?>

第一行,创建了一个整形变量,变量值是1。 此时保存整形1的这个zval的refcount为1。
第二行,创建了一个新的整形变量,变量也指向刚才创建的zval,并将这个zval的refcount加1,此时这个zval的refcount为2。
PHP提供了一个函数可以帮助我们了解这个过程debug_zval_dump:
复制代码 代码如下:

 $var = 1;
 debug_zval_dump($var);
 $var_dup = $var;
 debug_zval_dump($var);
?>

输出:
long(1) refcount(2)
long(1) refcount(3


如果你奇怪 ,var的refcount应该是1啊?
我们知道,对于简单变量,PHP是以传值的形式穿参数的。也就是说,当执行debug_zval_dump($var)的时候,$var会以传值的方式传递给debug_zval_dump,也就是会导致var的refcount加1,所以我们只要能看到,当变量赋值给一个变量以后,能导致zval的refcount加1这个事实即可。
现在我们回头看文章开头的代码, 当执行了最后一行unset($var)以后,会发生什么呢? 对,既是refcount减1,上代码:
复制代码 代码如下:

   $var = "laruence";
   $var_dup = $var;
   unset($var);
   debug_zval_dump($var_dup);
?>

输出:
string(8) "laruence" refcount(2


但是,对于下面的代码呢?
复制代码 代码如下:

   $var = "laruence";
   $var_dup = $var;
   $var = 1;
?>

很明显在这段代码执行以后,$var_dup的值应该还是”laruence”, 那么这又是怎么实现的呢?
这就是PHP的copy on write机制:
PHP在修改一个变量以前,会首先查看这个变量的refcount,如果refcount大于1,PHP就会执行一个分离的例程, 对于上面的代码,当执行到第三行的时候,PHP发现$var指向的zval的refcount大于1,那么PHP就会复制一个新的zval出来,将原zval的refcount减1,并修改symbol_table,使得$var和$var_dup分离(Separation)。这个机制就是所谓的copy on write(写时复制)。
上代码测试:
复制代码 代码如下:

   $var = "laruence";
   $var_dup = $var;
   $var = 1;
   debug_zval_dump($var);
   debug_zval_dump($var_dup);
?>

输出:
long(1) refcount(2)
string(8) "laruence" refcount(2


现在我们知道,当使用变量复制的时候 ,PHP内部并不是真正的复制,而是采用指向相同的结构来尽量节约开销。那么,对于PHP中的引用,那又是如何实现呢?
复制代码 代码如下:

   $var = "laruence";
   $var_ref = &$var;
   $var_ref = 1;
?>

这段代码结束以后,$var也会被间接的修改为1,这个过程称作(change on write:写时改变)。那么ZE是怎么知道,这次的复制是不需要Separation的呢?
这个时候就要用到zval中的is_ref字段了:
对于上面的代码,当第二行执行以后,$var所代表的zval的refcount变为2,并且同时置is_ref为1。
到第三行的时候,PHP先检查var_ref代表的zval的is_ref字段,如果为1,则不分离,大体逻辑示意如下:
复制代码 代码如下:

 if((*val)->is_ref || (*val)->refcount          //不执行Separation
        ... ;//process
  }

但是,问题又来了,对于如下的代码,又会怎样呢?
复制代码 代码如下:

   $var = "laruence";
   $var_dup = $var;
   $var_ref = &$var;
?>

对于上面的代码,存在一对copy on write的变量$var和$var_dup, 又有一对change on write机制的变量对$var和$var_ref,这个情况又是如何运作的呢?
当第二行执行的时候,和前面讲过的一样,$var_dup 和 $var 指向相同的zval, refcount为2.
当执行第三行的时候,PHP发现要操作的zval的refcount大于1,则,PHP会执行Separation, 将$var_dup分离出去,并将$var和$var_ref做change on write关联。也就是,refcount=2, is_ref=1;
基于这样的分析,我们就可以让debug_zval_dump出refcount为1的结果来:
复制代码 代码如下:

     $var = "laruence";
    $var_dup = &$var;
     debug_zval_dump($var);
?>

输出:
string(8) "laruence" refcount(1


详细原因,读者你只要稍加分析就能得出,我就不越俎代庖了。;)
这次我们介绍了PHP的变量分离机制,下次我会继续介绍如果在扩展中接收和传出PHP脚本中的参数。
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: Wie man alles in Myrise freischaltet
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Eine Anleitung zur Verwendung von Windows 11- und 10-Umgebungsvariablen für die Profilerstellung Eine Anleitung zur Verwendung von Windows 11- und 10-Umgebungsvariablen für die Profilerstellung Nov 01, 2023 pm 08:13 PM

Umgebungsvariablen sind der Pfad zum Speicherort (oder zur Umgebung), an dem Anwendungen und Programme ausgeführt werden. Sie können vom Benutzer erstellt, bearbeitet, verwaltet oder gelöscht werden und sind nützlich bei der Verwaltung des Verhaltens bestimmter Prozesse. So erstellen Sie eine Konfigurationsdatei, um mehrere Variablen gleichzeitig zu verwalten, ohne sie unter Windows einzeln bearbeiten zu müssen. So verwenden Sie Profile in Umgebungsvariablen Windows 11 und 10 Unter Windows gibt es zwei Sätze von Umgebungsvariablen – Benutzervariablen (gilt für den aktuellen Benutzer) und Systemvariablen (gilt global). Mit einem Tool wie PowerToys können Sie jedoch eine separate Konfigurationsdatei erstellen, um neue und vorhandene Variablen hinzuzufügen und alle auf einmal zu verwalten. So geht's: Schritt 1: Installieren Sie PowerToysPowerTo

So verwenden Sie Anführungszeichen in Apple Notes So verwenden Sie Anführungszeichen in Apple Notes Oct 12, 2023 pm 11:49 PM

In iOS 17 und macOS Sonoma hat Apple neue Formatierungsoptionen für Apple Notes hinzugefügt, darunter Anführungszeichen und einen neuen Monostyle-Stil. Hier erfahren Sie, wie Sie sie verwenden. Mit zusätzlichen Formatierungsoptionen in Apple Notes können Sie Ihren Notizen jetzt Anführungszeichen hinzufügen. Das Format der Blockzitate erleichtert das visuelle Versetzen von Textabschnitten mithilfe der Anführungszeichenleiste links vom Text. Tippen/klicken Sie einfach auf die Formatschaltfläche „Aa“ und wählen Sie die Option „Blockzitat“ aus, bevor Sie etwas eingeben oder wenn Sie sich in der Zeile befinden, die Sie in ein Blockzitat umwandeln möchten. Diese Option gilt für alle Texttypen, Stiloptionen und Listen, einschließlich Checklisten. Im selben Menü „Format“ finden Sie die neue Option „Einzelstil“. Dies ist eine Überarbeitung der vorherigen „gleichbreiten“

C++-Kompilierungsfehler: undefinierte Referenz, wie kann man ihn lösen? C++-Kompilierungsfehler: undefinierte Referenz, wie kann man ihn lösen? Aug 21, 2023 pm 08:52 PM

C++ ist eine beliebte Programmiersprache, aber während der Verwendung tritt häufig der Kompilierungsfehler „undefinierte Referenz“ auf, der große Probleme bei der Programmentwicklung mit sich bringt. In diesem Artikel wird die Lösung des Fehlers „Undefinierte Referenz“ sowohl hinsichtlich der Ursache als auch der Lösung erläutert. 1. Fehlerursache Wenn der C++-Compiler eine Quelldatei kompiliert, wird diese in zwei Phasen unterteilt: die Kompilierungsphase und die Verknüpfungsphase. Die Kompilierungsphase wandelt den Quellcode in den Quelldateien in Assemblercode um, während die Verknüpfungsphase verschiedene Quelldateien zu einer ausführbaren Datei kombiniert.

Strikter Modus für Variablen in PHP7: Wie können potenzielle Fehler reduziert werden? Strikter Modus für Variablen in PHP7: Wie können potenzielle Fehler reduziert werden? Oct 19, 2023 am 10:01 AM

In PHP7 wurde der strikte Modus eingeführt, der Entwicklern dabei helfen kann, potenzielle Fehler zu reduzieren. In diesem Artikel wird erklärt, was der strikte Modus ist und wie man den strikten Modus in PHP7 verwendet, um Fehler zu reduzieren. Gleichzeitig wird die Anwendung des strikten Modus anhand von Codebeispielen demonstriert. 1. Was ist der strikte Modus? Der strikte Modus ist eine Funktion in PHP7, die Entwicklern helfen kann, standardisierten Code zu schreiben und einige häufige Fehler zu reduzieren. Im strikten Modus gelten strenge Einschränkungen und Erkennungen für die Variablendeklaration, Typprüfung, Funktionsaufrufe usw. Passieren

Was sind Instanzvariablen in Java? Was sind Instanzvariablen in Java? Feb 19, 2024 pm 07:55 PM

Instanzvariablen in Java beziehen sich auf Variablen, die in der Klasse definiert sind, nicht in der Methode oder dem Konstruktor. Instanzvariablen werden auch Mitgliedsvariablen genannt. Jede Instanz einer Klasse verfügt über eine eigene Kopie der Instanzvariablen. Instanzvariablen werden während der Objekterstellung initialisiert und ihr Zustand wird während der gesamten Lebensdauer des Objekts gespeichert und beibehalten. Instanzvariablendefinitionen werden normalerweise an der Spitze der Klasse platziert und können mit einem beliebigen Zugriffsmodifikator deklariert werden, der öffentlich, privat, geschützt oder der Standardzugriffsmodifikator sein kann. Es hängt davon ab, was wir wollen

Welche Vorteile haben C++-Funktionen, die Referenztypen zurückgeben? Welche Vorteile haben C++-Funktionen, die Referenztypen zurückgeben? Apr 20, 2024 pm 09:12 PM

Zu den Vorteilen von Funktionen, die Referenztypen in C++ zurückgeben, gehören: Leistungsverbesserungen: Durch die Übergabe als Referenz wird das Kopieren von Objekten vermieden, wodurch Speicher und Zeit gespart werden. Direkte Änderung: Der Aufrufer kann das zurückgegebene Referenzobjekt direkt ändern, ohne es neu zuzuweisen. Einfachheit des Codes: Die Übergabe als Referenz vereinfacht den Code und erfordert keine zusätzlichen Zuweisungsvorgänge.

Wie erhalte ich Variablen aus der PHP-Methode mit Ajax? Wie erhalte ich Variablen aus der PHP-Methode mit Ajax? Mar 09, 2024 pm 05:36 PM

Die Verwendung von Ajax zum Abrufen von Variablen aus PHP-Methoden ist ein häufiges Szenario in der Webentwicklung. Durch Ajax kann die Seite dynamisch abgerufen werden, ohne dass die Daten aktualisiert werden müssen. In diesem Artikel stellen wir vor, wie man Ajax verwendet, um Variablen aus PHP-Methoden abzurufen, und stellen spezifische Codebeispiele bereit. Zuerst müssen wir eine PHP-Datei schreiben, um die Ajax-Anfrage zu verarbeiten und die erforderlichen Variablen zurückzugeben. Hier ist ein Beispielcode für eine einfache PHP-Datei getData.php:

Mindmap der Python-Syntax: Vertiefendes Verständnis der Codestruktur Mindmap der Python-Syntax: Vertiefendes Verständnis der Codestruktur Feb 21, 2024 am 09:00 AM

Python wird aufgrund seiner einfachen und leicht lesbaren Syntax in einer Vielzahl von Bereichen häufig verwendet. Es ist von entscheidender Bedeutung, die Grundstruktur der Python-Syntax zu beherrschen, um sowohl die Programmiereffizienz zu verbessern als auch ein tiefes Verständnis für die Funktionsweise des Codes zu erlangen. Zu diesem Zweck bietet dieser Artikel eine umfassende Mindmap, die verschiedene Aspekte der Python-Syntax detailliert beschreibt. Variablen und Datentypen Variablen sind Container, die zum Speichern von Daten in Python verwendet werden. Die Mindmap zeigt gängige Python-Datentypen, einschließlich Ganzzahlen, Gleitkommazahlen, Zeichenfolgen, boolesche Werte und Listen. Jeder Datentyp hat seine eigenen Eigenschaften und Betriebsmethoden. Operatoren Operatoren werden verwendet, um verschiedene Operationen an Datentypen auszuführen. Die Mindmap deckt die verschiedenen Operatortypen in Python ab, z. B. arithmetische Operatoren und Verhältnisse

See all articles