php数组时按值传递还是按地址传递
php数组时按值传递还是按地址传递
一、总结
1、数组都是按值:php普通变量和数组的赋值(=)是按值传递,对象的赋值(=)是按址传递
2、对象和按值和按址:对象的clone(用clone关键字)是按值传递
二、PHP 数组的拷贝是按值传递 or 按引用传递
在记忆中 PHP 简单变量的拷贝是按值传递,数组和对象的拷贝是按引用传递,即通过引用来实现。
简单变量和对象好理解:
<?php // 简单变量的拷贝 $a = 'human'; $b = $a; $b = 'cat'; var_dump($a); // string 'human' (length=5) // 对象的拷贝 class A{} $a = new A(); $b = $a; $b->name = 'jack'; var_dump($a); // object(A)[1] public 'name' => string 'jack' (length=4)
对象 $a 和 对象 $b 的内存地址指向了同一个地方,即针对 $a 和 $b 所做的操作都针对同一个实例。
PHP 中可以通过 clone 关键字按值拷贝对象:clone关键字让对象按值传递,因为clone就是拷贝
1
2
3
4
5
6
7
8
9
10
|
<?php class A{ public $name = 'Vardy' ; }<br> $a = new A(); $b = clone $a ; $b ->name = 'dee' ; var_dump( $a ); // object(A)[1] public 'name' => string 'Vardy' (length=5) var_dump( $b ); // object(A)[2] public 'name' => string 'dee' (length=3) |
数组:
1
2
3
4
5
6
7
8
9
10
|
<?php // 数组的拷贝 $a = [ 'human' , 'orc' ]; $b = $a ; $b [0] = 'elve' ; var_dump( $a ); // array (size=2) // 0 => string 'human' (length=5) // 1 => string 'orc' (length=3) |
这样看,数组的拷贝是按值传递的.
另一个例子 数组的迭代器:
1
2
3
4
5
6
7
8
9
|
<?php $a = [ 'human' , 'orc' , 'elven' , 'undead' ]; next( $a ); $b = $a ; // 此时指针位置也随着数组的复制而复制 var_dump(current( $a )); // string 'orc' (length=3) var_dump(current( $b )); // string 'orc' (length=3) |
当数组拷贝时,数组的指针位置也随着复制。
(next:http://php.net/manual/zh/function.next.php
current:http://php.net/manual/zh/function.current.php)
1
2
3
4
5
6
7
8
9
10
|
<?php $a = [ 'human' , 'orc' , 'elven' , 'undead' ]; end ( $a ); next( $a ); // 数组指针非法,返回 FALSE $b = $a ; var_dump(current( $a )); // string 'human' (length=5) var_dump(current( $b )); // boolean false |
当数组在拷贝前,指针的位置是非法时,拷贝后分别打印两个数组指针所指向的当前单元时,出现了不一样的情况。
原因是数组变量发生拷贝后,两个变量中先发生写操作的,其指针被初始化,即指向第一个元素,而 current 方法也会产生写操作,因此 $a 的数组指针当前指向的是 'human',而 $b current 方法则返回 FALSE。
以下代码同理, $b 首先发生了写操作:
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php $a = [ 'human' , 'orc' , 'elven' , 'undead' ]; end ( $a ); next( $a ); $b = $a ; $b [] = 'dwarf' ; var_dump(current( $a )); // boolean false var_dump(current( $b )); // string 'human' (length=5) |
解析:数组的拷贝是值传递。PHP 在管理内存方面有一个机制叫写时复制(COW,Copy On Write),保证了变量间复制值不浪费内存:当一个变量的值复制到另一个变量时,PHP 没有为复制值使用更多的内存,相反,它会更新符号表来说明两个变量拥有相同的内存块,所以当执行下面的代码时并没有创建一个新的数组:
1
2
3
4
|
<?php $a = [ 'human' , 'orc' , 'elven' , 'undead' ]; $b = $a ; |
当修改了 $a 或 $b 任意一个副本时,PHP 将分配所需的内存来进行复制:
1
|
$b [] = 'dwarf' ; |
参考:
Programming PHP 3rd Edition
参考:
PHP 数组的拷贝是按值传递 or 按引用传递 - 黄棣-dee - 博客园
https://www.cnblogs.com/dee0912/p/5605323.html