Home > Backend Development > PHP Tutorial > Detailed introduction to reference assignment and value assignment of PHP variables (code)

Detailed introduction to reference assignment and value assignment of PHP variables (code)

不言
Release: 2023-04-04 06:16:01
Original
7349 people have browsed it

This article brings you a detailed introduction (code) about reference assignment and value assignment of PHP variables. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you. .

1. Use memory_get_usage() to check PHP memory usage

1. Pass value assignment

// 定义一个变量
$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());
Copy after login

Output result:

int(989768)
int(989856)
int(1855608)
Copy after login

Define a Variable $a = range(0, 10000);

Detailed introduction to reference assignment and value assignment of PHP variables (code)

##$b = $a;

Detailed introduction to reference assignment and value assignment of PHP variables (code)

Modify a$a = range(0, 10000);

Detailed introduction to reference assignment and value assignment of PHP variables (code)

PHP copy-on-write mechanism (Copy-on-Write, also abbreviated as COW)

As the name suggests, a copy of the memory is actually copied for modification when writing.

COW was first used in Unix systems to optimize thread and memory usage, and was later widely used in various programming languages, such as C's STL, etc.
In the PHP kernel, COW is also the main memory optimization method.
When assigning a value to a variable through variable assignment, new memory will not be allocated to store the value of the new variable, but the memory will simply be shared through a counter. Only when the value of the variable pointed to by one of the references changes, new space is allocated to save the value content to reduce memory usage.
In many scenarios, PHP uses COW for memory optimization. For example: multiple assignments of variables, passing function parameters, and modifying actual parameters in the function body, etc.

2. Reference assignment

// 定义一个变量
$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());
Copy after login

Output result:

int(989760)
int(989848)
int(989840)
Copy after login

Define a variable$a = range(0, 10000);

Detailed introduction to reference assignment and value assignment of PHP variables (code)

Define variable b and assign the reference of variable a to b $b = &$a;

Detailed introduction to reference assignment and value assignment of PHP variables (code)

##Modify a

$a = range(0, 10000);

Detailed introduction to reference assignment and value assignment of PHP variables (code) 2. Use

xdebug_debug_zval()

to view the reference status of variables

xdebug_debug_zval( )

Used to display variable information. The xdebug extension needs to be installed. 1. Pass-by-value assignment

$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');
Copy after login

Output result:

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
Copy after login

Define variables

$a = 1; <div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">$a = 1; xdebug_debug_zval('a');</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div>Output

a: (refcount=1, is_ref=0)=1
Copy after login
Copy after login

refcount=1

means that the number of references to the memory address pointed to by the variable becomes 1is_ref=0
means that the variable Instead of quoting

Detailed introduction to reference assignment and value assignment of PHP variables (code)

, define the variable

$b and assign the value of $a to $b, $b = $a;
$b = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
Copy after login
Output

a: (refcount=2, is_ref=0)=1
b: (refcount=2, is_ref=0)=1
Copy after login

refcount=2

indicates that the variable points to The number of references to the memory address becomes 2is_ref=0
, indicating that the variable is not a reference

Detailed introduction to reference assignment and value assignment of PHP variables (code)## Write operation to variable

$a

$a = 2;<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">$a = 2; xdebug_debug_zval('a'); xdebug_debug_zval('b');</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div>Output
a: (refcount=1, is_ref=0)=2
b: (refcount=1, is_ref=0)=1
Copy after login

Because of the COW mechanism, the variable

When $a

performs a write operation, a new memory space will be allocated for variable

$a to store the value of variable $a. At this time, the number of references to the memory addresses pointed to by $a and
$b becomes 1.

Detailed introduction to reference assignment and value assignment of PHP variables (code)2. Reference assignment

$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');
Copy after login
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
Copy after login

Define variables

$a = 1;

<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">$a = 1; xdebug_debug_zval('a');</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div>Output
a: (refcount=1, is_ref=0)=1
Copy after login
Copy after login

refcount=1

Indicates that the number of references to the memory address pointed to by the variable becomes 1

is_ref=0 Indicates that the variable is not a reference

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

$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
Copy after login

输出

a: (refcount=2, is_ref=1)=1
b: (refcount=2, is_ref=1)=1
Copy after login

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

Detailed introduction to reference assignment and value assignment of PHP variables (code)

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

<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">$a = 2; xdebug_debug_zval('a'); xdebug_debug_zval('b');</pre><div class="contentsignin">Copy after login</div></div><div class="contentsignin">Copy after login</div></div>

输出

a: (refcount=2, is_ref=1)=2
b: (refcount=2, is_ref=1)=2
Copy after login

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

Detailed introduction to reference assignment and value assignment of PHP variables (code)

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

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

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

echo $a;
Copy after login

输出

1
Copy after login
Copy after login

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

$a = 1;
$b = &$a;
Copy after login

Detailed introduction to reference assignment and value assignment of PHP variables (code)

销毁 $b

unset($b);
Copy after login

Detailed introduction to reference assignment and value assignment of PHP variables (code)

输出 $a

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

echo $a;
Copy after login

输出

1
Copy after login
Copy after login

四、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');
Copy after login
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 }
Copy after login

实例化对象 $p1 = new Person;

$p1 = new Person;
xdebug_debug_zval('p1');
Copy after login

输出

p1: (refcount=1, is_ref=0)=class Person { public $age = (refcount=2, is_ref=0)=1 }
Copy after login

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

$p1 赋给 $p2

$p2 = $p1;
xdebug_debug_zval('p1');
xdebug_debug_zval('p2');
Copy after login

输出

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 }
Copy after login

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

Detailed introduction to reference assignment and value assignment of PHP variables (code)

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

$p2->age = 2;
xdebug_debug_zval('p1');
xdebug_debug_zval('p2');
Copy after login

输出

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 }
Copy after login

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

五、实战例题分析

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

1. 第一次循环

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

$k = 0
$v = 'a'
$d[$k] = $d[0] = 'a'
Copy after login

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

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

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

$v = &$d[0]
Copy after login

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

第一次循环后 $d 的值:

['a', 'b', 'c']
Copy after login

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'
Copy after login

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

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

$v = &$d[1]
Copy after login

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

第二次循环后 $d 的值

['b', 'b', 'c']
Copy after login

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'
Copy after login

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

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

$v = &$d[2]
Copy after login

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

第三次循环后 $d 的值

['b', 'c', 'c']
Copy after login

4. 实测

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

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

print_r($d);
Copy after login

输出:

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
)
Copy after login

相关推荐:

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

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

The above is the detailed content of Detailed introduction to reference assignment and value assignment of PHP variables (code). For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template