|
導讀網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立... 網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立在超文本基礎之上的。超級文本標記語言之所以稱為超文本標記語言,是因為文本中包含了所謂“超級鏈接”點。 本篇文章給大家帶來的內容是關于php變量的引用賦值與傳值賦值的詳細介紹(代碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。一、使用 memory_get_usage() 查看PHP內存使用量1. 傳值賦值// 定義一個變量
$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()); 輸出結果: int(989768)
int(989856)
int(1855608) 定義一個變量 $a = range(0, 10000);
$b = $a;

對a進行修改 $a = range(0, 10000);
PHP寫時復制機制(Copy-on-Write,也縮寫為COW) 顧名思義,就是在寫入時才真正復制一份內存進行修改。 COW最早應用在Unix系統中對線程與內存使用的優化,后面廣泛的被使用在各種編程語言中,如C++的STL等。 在PHP內核中,COW也是主要的內存優化手段。 在通過變量賦值的方式賦值給變量時,不會申請新內存來存放新變量的值,而是簡單的通過一個計數器來共用內存。只有在其中的一個引用指向變量的值發生變化時,才申請新空間來保存值內容,以減少對內存的占用。 在很多場景下PHP都使用COW進行內存的優化。比如:變量的多次賦值、函數參數傳遞,并在函數體內修改實參等。 2. 引用賦值// 定義一個變量
$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()); 輸出結果: int(989760)
int(989848)
int(989840) 定義一個變量 $a = range(0, 10000);
定義變量b,將a變量的引用賦給b $b = &$a;
對a進行修改 $a = range(0, 10000);
二、使用 xdebug_debug_zval() 查看變量的引用情況xdebug_debug_zval() 用于顯示變量的信息。需要安裝xdebug擴展。
1. 傳值賦值$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');輸出結果: 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 定義變量 $a = 1;$a = 1;
xdebug_debug_zval('a');輸出 a: (refcount=1, is_ref=0)=1 refcount=1 表示該變量指向的內存地址的引用個數變為1
is_ref=0 表示該變量不是引用

定義變量 $b ,把 $a 的值賦給 $b, $b = $a;$b = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');輸出 a: (refcount=2, is_ref=0)=1
b: (refcount=2, is_ref=0)=1 refcount=2 表示該變量指向的內存地址的引用個數變為2
is_ref=0 表示該變量不是引用

對變量 $a 進行寫操作 $a = 2;$a = 2;
xdebug_debug_zval('a');
xdebug_debug_zval('b');輸出 a: (refcount=1, is_ref=0)=2
b: (refcount=1, is_ref=0)=1 因為COW機制,對變量 $a 進行寫操作時,會為變量 $a 新分配一塊內存空間,用于存儲變量 $a 的值。 此時 $a 和 $b 指向的內存地址的引用個數都變為1。 
2. 引用賦值$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');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 定義變量 $a = 1;$a = 1;
xdebug_debug_zval('a');輸出 a: (refcount=1, is_ref=0)=1 refcount=1 表示該變量指向的內存地址的引用個數變為1
is_ref=0 表示該變量不是引用

定義變量 $b ,把 $a 的引用賦給 $b, $b = &$a;$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');輸出 a: (refcount=2, is_ref=1)=1
b: (refcount=2, is_ref=1)=1 refcount=2 表示該變量指向的內存地址的引用個數變為2
is_ref=1 表示該變量是引用

對變量 $a 進行寫操作 $a = 2;$a = 2;
xdebug_debug_zval('a');
xdebug_debug_zval('b');輸出 a: (refcount=2, is_ref=1)=2
b: (refcount=2, is_ref=1)=2 因為變量 $a 和變量 $b 指向相同的內存地址,其實引用。 對變量 $a 進行寫操作時,會直接修改指向的內存空間的值,因此變量 $b 的值會跟著一起改變。 
三、當變量時引用時,unset()只會取消引用,不會銷毀內存空間$a = 1;
$b = &$a;
// unset 只會取消引用,不會銷毀內存空間
unset($b);
echo $a; 輸出 1 定義變量 $a ,并將 $a 的引用賦給變量 $b$a = 1;
$b = &$a; 
銷毀 $bunset($b); 
輸出 $a雖然銷毀的 $b,但是 $a 的引用和內存空間依舊存在。 echo $a; 輸出 1 四、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');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 }實例化對象 $p1 = new Person;$p1 = new Person;
xdebug_debug_zval('p1');輸出 p1: (refcount=1, is_ref=0)=class Person { public $age = (refcount=2, is_ref=0)=1 }refcount=1 表示該變量指向的內存地址的引用個數變為1
is_ref=0 表示該變量不是引用
把 $p1 賦給 $p2$p2 = $p1;
xdebug_debug_zval('p1');
xdebug_debug_zval('p2');輸出 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 }refcount=2 表示該變量指向的內存地址的引用個數變為2

對 $p2 中的屬性 age 進行寫操作$p2->age = 2;
xdebug_debug_zval('p1');
xdebug_debug_zval('p2');輸出 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 }因為php中對象本身就是引用賦值。對 $p2 中的屬性 age 進行寫操作時,會直接修改指向的內存空間的值,因此變量 $p1 的 age 屬性的值會跟著一起改變。 五、實戰例題分析/**
* 寫出如下程序的輸出結果
*
* $d = ['a', 'b', 'c'];
*
* foreach($d as $k => $v)
* {
* $v = &$d[$k];
* }
*
* 程序運行時,每一次循環結束后變量 $d 的值是什么?請解釋。
* 程序執行完成后,變量 $d 的值是什么?請解釋。
*/1. 第一次循環推算出進入 foreach 時 $v、$d[$k] 的值$k = 0
$v = 'a'
$d[$k] = $d[0] = 'a' 此時,$v 和 $d[0] 在內存中分別開辟了一塊空間 ![$v 和 $d[0] 在內存中分別開辟了一塊空間](http://md.ws65535.top/xsj/201... $v = &$d[0] 改變了 $v 指向的內存地址
$v = &$d[0] ![$v = &$d[0] 改變了 $val 指向的內存地址](http://md.ws65535.top/xsj/201... 第一次循環后 $d 的值:['a', 'b', 'c'] 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' ![$d[2] = ‘b’](http://md.ws65535.top/xsj/201... $v = &$d[1] 改變了 $v 指向的內存地址
$v = &$d[1] ![$v = &$d[1]](http://md.ws65535.top/xsj/201... 第二次循環后 $d 的值['b', 'b', 'c'] 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' ![$d[2] = ‘c’](http://md.ws65535.top/xsj/201... $v = &$d[2] 改變了 $v 指向的內存地址
$v = &$d[2] ![$v = &$d[2]](http://md.ws65535.top/xsj/201... 第三次循環后 $d 的值['b', 'c', 'c'] 4. 實測$d = ['a', 'b', 'c'];
foreach ($d as $k=>$v)
{
$v = &$d[$k];
print_r($d);
}
print_r($d);輸出: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
)相關推薦:
以上就是php變量的引用賦值與傳值賦值的詳細介紹(代碼)的詳細內容,更多請關注php中文網其它相關文章!
網站建設是一個廣義的術語,涵蓋了許多不同的技能和學科中所使用的生產和維護的網站。
|