在記憶中 PHP 簡單變量的拷貝是按值傳遞,數組和對象的拷貝是按引用傳遞,即經過引用來實現。php
簡單變量和對象好理解:html
<?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 關鍵字按值拷貝對象:函數
<?php class A{ public $name = 'Vardy'; }
$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)
數組:post
<?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)
這樣看,數組的拷貝是按值傳遞的.url
另外一個例子 數組的迭代器:spa
<?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)
當數組拷貝時,數組的指針位置也隨着複製。.net
(next:http://php.net/manual/zh/function.next.php指針
current:http://php.net/manual/zh/function.current.php)code
<?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 首先發生了寫操做:
<?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 沒有爲複製值使用更多的內存,相反,它會更新符號表來講明兩個變量擁有相同的內存塊,因此當執行下面的代碼時並無建立一個新的數組:
<?php $a = ['human', 'orc', 'elven', 'undead']; $b = $a;
當修改了 $a 或 $b 任意一個副本時,PHP 將分配所需的內存來進行復制:
$b[] = 'dwarf';
參考:
Programming PHP 3rd Edition