Maison > développement back-end > tutoriel php > Introduction détaillée à l'affectation de références et à l'affectation de valeurs des variables PHP (code)

Introduction détaillée à l'affectation de références et à l'affectation de valeurs des variables PHP (code)

不言
Libérer: 2023-04-04 06:16:01
original
7349 Les gens l'ont consulté

Cet article vous apporte une introduction détaillée (code) sur l'attribution de références et l'attribution de valeurs aux variables PHP. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

1. Utilisez memory_get_usage() pour vérifier l'utilisation de la mémoire PHP

1. Attribution de la valeur de passage

// 定义一个变量
$a = range(0, 10000);
var_dump(memory_get_usage());

// 定义变量b,将a变量的值赋值给b
$b = $a;
var_dump(memory_get_usage());

// 对a进行修改
// COW: Copy-On-Write
$a = range(0, 10000);
var_dump(memory_get_usage());
Copier après la connexion

Résultat de sortie :

int(989768)
int(989856)
int(1855608)
Copier après la connexion

Définir une variable$a = range(0, 10000);

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

$b = $a;

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

Modifier une$a = range(0, 10000);

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

copie sur écriture PHP Mécanisme (Copy-on-Write, également abrégé en COW)

Comme son nom l'indique, il copie en fait une copie de la mémoire pour la modifier lors de l'écriture.
COW a d'abord été utilisé dans les systèmes Unix pour optimiser l'utilisation des threads et de la mémoire, puis a été largement utilisé dans divers langages de programmation, tels que STL de C++, etc.
Dans le noyau PHP, COW est également la principale méthode d'optimisation de la mémoire.
Lors de l'attribution d'une valeur à une variable via l'affectation de variable, une nouvelle mémoire ne sera pas allouée pour stocker la valeur de la nouvelle variable, mais la mémoire sera simplement partagée via un compteur. Ce n'est que lorsque la valeur de la variable pointée par l'une des références change qu'un nouvel espace est alloué pour enregistrer le contenu de la valeur afin de réduire l'utilisation de la mémoire.
Dans de nombreux scénarios, PHP utilise COW pour l'optimisation de la mémoire. Par exemple : affectations multiples de variables, transmission de paramètres de fonction et modification des paramètres réels dans le corps de la fonction, etc.

2. Affectation de référence

// 定义一个变量
$a = range(0, 10000);
var_dump(memory_get_usage());

// 定义变量b,将a变量的引用赋给b
$b = &$a;
var_dump(memory_get_usage());

// 对a进行修改
$a = range(0, 10000);
var_dump(memory_get_usage());
Copier après la connexion

Résultat de sortie :

int(989760)
int(989848)
int(989840)
Copier après la connexion

Définir une variable$a = range(0, 10000);

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

Définir la variable b et attribuer la référence de la variable a à b $b = &$a;

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

Modifier un$a = range(0, 10000);

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

2. Utilisez xdebug_debug_zval() pour visualiser la référence du variable La casse

xdebug_debug_zval() est utilisée pour afficher des informations sur une variable. L'extension xdebug doit être installée.

1. Affectation de valeur

$a = 1;
xdebug_debug_zval('a');

// 定义变量b,把a的值赋值给b
$b = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');

// a进行写操作
$a = 2;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
Copier après la connexion

Résultat de sortie :

a: (refcount=1, is_ref=0)=1
a: (refcount=2, is_ref=0)=1
b: (refcount=2, is_ref=0)=1
a: (refcount=1, is_ref=0)=2
b: (refcount=1, is_ref=0)=1
Copier après la connexion

Définir les variables$a = 1;

$a = 1;
xdebug_debug_zval('a');
Copier après la connexion
Copier après la connexion

Sortie

a: (refcount=1, is_ref=0)=1
Copier après la connexion
Copier après la connexion

refcount=1 signifie que le nombre de références à l'adresse mémoire pointée par la variable devient 1
is_ref=0 signifie que la variable n'est pas une référence

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

Définir la variable $b, attribuer la valeur de $a à $b, $b = $a;

$b = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
Copier après la connexion

sortie

a: (refcount=2, is_ref=0)=1
b: (refcount=2, is_ref=0)=1
Copier après la connexion

refcount=2 signifie que le nombre de références à l'adresse mémoire pointée par la variable devient 2
is_ref=0 signifie que la variable n'est pas une référence

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

Ecriture dans la variable $a$a = 2;

$a = 2;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
Copier après la connexion
Copier après la connexion

Sortie

a: (refcount=1, is_ref=0)=2
b: (refcount=1, is_ref=0)=1
Copier après la connexion

En raison du mécanisme COW, écriture dans la variable $a Lors de l'exécution d'une opération d'écriture, un nouvel espace mémoire sera alloué à la variable $a pour stocker la valeur de la variable $a.
A ce moment, le nombre de références à l'adresse mémoire pointée par $a et $b devient tous deux 1.

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

2. Affectation de référence

$a = 1;
xdebug_debug_zval('a');

// 定义变量b,把a的引用赋给b
$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');

// a进行写操作
$a = 2;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
Copier après la connexion
a: (refcount=1, is_ref=0)=1
a: (refcount=2, is_ref=1)=1
b: (refcount=2, is_ref=1)=1
a: (refcount=2, is_ref=1)=2
b: (refcount=2, is_ref=1)=2
Copier après la connexion

Définir les variables$a = 1;

$a = 1;
xdebug_debug_zval('a');
Copier après la connexion
Copier après la connexion

Sortie

a: (refcount=1, is_ref=0)=1
Copier après la connexion
Copier après la connexion

refcount=1 signifie que le nombre de références à l'adresse mémoire pointée par la variable devient 1
is_ref=0 signifie que la variable n'est pas une référence

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

定义变量 $b ,把 $a 的引用赋给 $b$b = &$a;

$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
Copier après la connexion

输出

a: (refcount=2, is_ref=1)=1
b: (refcount=2, is_ref=1)=1
Copier après la connexion

refcount=2 表示该变量指向的内存地址的引用个数变为2
is_ref=1 表示该变量是引用

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

对变量 $a 进行写操作 $a = 2;

$a = 2;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
Copier après la connexion
Copier après la connexion

输出

a: (refcount=2, is_ref=1)=2
b: (refcount=2, is_ref=1)=2
Copier après la connexion

因为变量 $a 和变量 $b 指向相同的内存地址,其实引用。
对变量 $a 进行写操作时,会直接修改指向的内存空间的值,因此变量 $b 的值会跟着一起改变。

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

三、当变量时引用时,unset()只会取消引用,不会销毁内存空间

$a = 1;
$b = &$a;

// unset 只会取消引用,不会销毁内存空间
unset($b);

echo $a;
Copier après la connexion

输出

1
Copier après la connexion
Copier après la connexion

定义变量 $a ,并将 $a 的引用赋给变量  $b

$a = 1;
$b = &$a;
Copier après la connexion

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

销毁 $b

unset($b);
Copier après la connexion

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

输出 $a

虽然销毁的 $b,但是 $a 的引用和内存空间依旧存在。

echo $a;
Copier après la connexion

输出

1
Copier après la connexion
Copier après la connexion

四、php中对象本身就是引用赋值

class Person
{
    public $age = 1;
}

$p1 = new Person;
xdebug_debug_zval('p1');

$p2 = $p1;
xdebug_debug_zval('p1');
xdebug_debug_zval('p2');

$p2->age = 2;
xdebug_debug_zval('p1');
xdebug_debug_zval('p2');
Copier après la connexion
p1: (refcount=1, is_ref=0)=class Person { public $age = (refcount=2, is_ref=0)=1 }
p1: (refcount=2, is_ref=0)=class Person { public $age = (refcount=2, is_ref=0)=1 }
p2: (refcount=2, is_ref=0)=class Person { public $age = (refcount=2, is_ref=0)=1 }
p1: (refcount=2, is_ref=0)=class Person { public $age = (refcount=1, is_ref=0)=2 }
p2: (refcount=2, is_ref=0)=class Person { public $age = (refcount=1, is_ref=0)=2 }
Copier après la connexion

实例化对象 $p1 = new Person;

$p1 = new Person;
xdebug_debug_zval('p1');
Copier après la connexion

输出

p1: (refcount=1, is_ref=0)=class Person { public $age = (refcount=2, is_ref=0)=1 }
Copier après la connexion

refcount=1 表示该变量指向的内存地址的引用个数变为1
is_ref=0 表示该变量不是引用

$p1 赋给 $p2

$p2 = $p1;
xdebug_debug_zval('p1');
xdebug_debug_zval('p2');
Copier après la connexion

输出

p1: (refcount=2, is_ref=0)=class Person { public $age = (refcount=2, is_ref=0)=1 }
p2: (refcount=2, is_ref=0)=class Person { public $age = (refcount=2, is_ref=0)=1 }
Copier après la connexion

refcount=2 表示该变量指向的内存地址的引用个数变为2

Introduction détaillée à laffectation de références et à laffectation de valeurs des variables PHP (code)

$p2 中的属性 age 进行写操作

$p2->age = 2;
xdebug_debug_zval('p1');
xdebug_debug_zval('p2');
Copier après la connexion

输出

p1: (refcount=2, is_ref=0)=class Person { public $age = (refcount=1, is_ref=0)=2 }
p2: (refcount=2, is_ref=0)=class Person { public $age = (refcount=1, is_ref=0)=2 }
Copier après la connexion

因为php中对象本身就是引用赋值。对 $p2 中的属性 age 进行写操作时,会直接修改指向的内存空间的值,因此变量 $p1age 属性的值会跟着一起改变。

五、实战例题分析

/**
 * 写出如下程序的输出结果
 *
 * $d = ['a', 'b', 'c'];
 *
 * foreach($d as $k => $v)
 * {
 *    $v = &$d[$k];
 * }
 * 
 * 程序运行时,每一次循环结束后变量 $d 的值是什么?请解释。
 * 程序执行完成后,变量 $d 的值是什么?请解释。
 */
Copier après la connexion

1. 第一次循环

推算出进入 foreach$v$d[$k] 的值

$k = 0
$v = 'a'
$d[$k] = $d[0] = 'a'
Copier après la connexion

此时,$v$d[0] 在内存中分别开辟了一块空间

![$v 和 $d[0] 在内存中分别开辟了一块空间](http://md.ws65535.top/xsj/201...

$v = &$d[0] 改变了 $v 指向的内存地址

$v = &$d[0]
Copier après la connexion

![$v = &$d[0] 改变了 $val 指向的内存地址](http://md.ws65535.top/xsj/201...

第一次循环后 $d 的值:

['a', 'b', 'c']
Copier après la connexion

2. 第二次循环

进入 foreach$v 被赋值为 'b',此时$v指向的内存地址与 $d[0] 相同,且为引用,因此 $d[0] 的值被修改为 'b'

$v = 'b'  => $d[0] = 'b'

![$v = ‘b’  => $d[0] = ‘b’](http://md.ws65535.top/xsj/201...

推算出进入 foreach$d[$k] 的值

$k = 1
$d[$k] = $d[1] = 'b'
Copier après la connexion

![$d[2] = ‘b’](http://md.ws65535.top/xsj/201...

$v = &$d[1] 改变了 $v 指向的内存地址

$v = &$d[1]
Copier après la connexion

![$v = &$d[1]](http://md.ws65535.top/xsj/201...

第二次循环后 $d 的值

['b', 'b', 'c']
Copier après la connexion

3. 第三次循环

进入 foreach$v 被赋值为 'c',此时$v指向的内存地址与 $d[1] 相同,且为引用,因此 $d[1] 的值被修改为 'c'

$v = 'c'  => $d[1] = 'c'

![$v = ‘c’  => $d[1] = ‘c’](http://md.ws65535.top/xsj/201...

推算出进入 foreach$d[$k] 的值

$k = 2
$d[2] = 'c'
Copier après la connexion

![$d[2] = ‘c’](http://md.ws65535.top/xsj/201...

$v = &$d[2] 改变了 $v 指向的内存地址

$v = &$d[2]
Copier après la connexion

![$v = &$d[2]](http://md.ws65535.top/xsj/201...

第三次循环后 $d 的值

['b', 'c', 'c']
Copier après la connexion

4. 实测

$d = ['a', 'b', 'c'];

foreach ($d as $k=>$v)
{
    $v = &$d[$k];
    print_r($d);
}

print_r($d);
Copier après la connexion

输出:

Array
(
    [0] => a
    [1] => b
    [2] => c
)
Array
(
    [0] => b
    [1] => b
    [2] => c
)
Array
(
    [0] => b
    [1] => c
    [2] => c
)
Array
(
    [0] => b
    [1] => c
    [2] => c
)
Copier après la connexion

相关推荐:

php 传值赋值与引用赋值的区别_PHP教程

PHP变量赋值、代入给JavaScript中的变量,赋值javascript

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal