關於php引用的一般問題大家看資料就行了,這次我們來聊點有趣的東西。今天乙個朋友在群裡面問起來乙個關於變數引用賦值的問題,問題本身很簡單,我突然想做乙個實驗,來看看array直接賦值和引用賦值效能上的差別,寫完**發現另外乙個問題.請看**
<?php
$a = array_fill(0, 1000000, 10);
function test_time_cost($loop, $func) ;
function fetch_data($b) {}
test_time_cost(10000, function() );
test_time_cost(10000, function() );
**在第二個測試函式裡出錯了,記憶體不夠了。但是問題是php在變數賦值以後,如果目標變數未被使用,是不會執行賦值操作的。因為php語言在處理變數賦值時實際上是給$a和$b開闢了乙個變數容器,在容器裡$a和$b是對等的,可以簡單理解為引用關係。但是當$b被改動時,$b就會被移出容器。
<?php
$a = array_fill(0, 1000000, 10);
$b = $a; // 記憶體不增加
$b[0] = 10; // $a所佔記憶體會賦值給$b
fetch_data函式實際上未對變數做任何處理,怎麼會觸發複製呢?於是我寫了下面的**
<?php
echo "memory_limit = " . ini_get('memory_limit') ."\n";
echo "memory init = " . memory_get_usage(true) . "\n";
$a = array_fill(0, 10000, 10);
echo "memory after a = " . memory_get_usage(true) ."\n";
$c = $b = $a;
echo "memory after c,b = " . memory_get_usage(true) ."\n";
function fetch_data($m)
fetch_data($a);
global $a; fetch_data($a);
執行結果如下
memory_limit = 128m
memory init = 786432
memory after a = 1835008
memory after c,b = 1835008
memory in fetch_data = 1835008
memory in fetch_data = 3670016
說明在宣告global $a以後發生了變數拷貝賦值,既然是這樣,看看php的文件吧,是不是對global申明的變數有什麼特殊處理。看了一遍,沒什麼特殊的,就是建立引用物件。於是我又仔細看了一次php關於引用的說明, 我這次準備跟蹤一下引用計數器
$a = array_fill(0, 1, 10);
$c = $b = $a;
echo "c,b,a\n";
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
echo "changing b\n";
$b[0] = 8;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
echo "global a\n";
global $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
echo "c,b,global a\n";
$c = $b = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');
執行的結果
c,b,a
a: (refcount=3, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
b: (refcount=3, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
c: (refcount=3, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
changing b
a: (refcount=2, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
b: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)=8)
c: (refcount=2, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
global a
a: (refcount=1, is_ref=1)=array (0 => (refcount=2, is_ref=0)=10)
b: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)=8)
c: (refcount=1, is_ref=0)=array (0 => (refcount=2, is_ref=0)=10)
c,b,global a
a: (refcount=1, is_ref=1)=array (0 => (refcount=2, is_ref=0)=10)
b: (refcount=2, is_ref=0)=array (0 => (refcount=2, is_ref=0)=10)
c: (refcount=2, is_ref=0)=array (0 => (refcount=2, is_ref=0)=10)
終於看出了問題,在沒有global $a的時候,a,b,c在同乙個變數容器裡,所以沒有發生複製行為。但是在宣告global $a以後再進行複製,b,c不和a在同一容器了。我覺得原因就在於$a這個時候已經不是簡單的變數了,可以理解為乙個指標。php在這個時候沒有辦法建立變數容器同時給變數和指標,所以拷貝於是就發生了。
深入理解PHP中賦值與引用
先看下面的問題 a 10 將常量值賦給變數,會為a分配記憶體空間 b a 變數賦值給變數,是不是copy了乙份副本,b也分配了記憶體空間呢?c a 引用是不會為c分配空間的,c和a是共用乙份空間的。對於中間的那個問題,你的答案是什麼呢?在今天之前,我的答案是會為b分配記憶體空間。因為我是這麼理解的 ...
深入理解PHP物件賦值
1 2 深入理解php物件賦值 3echo 45 obj new stdclass 6 obj name pig 7var dump obj object stdclass 1 1 89 copy obj obj copy都是new stdclass返回的同乙個識別符號的拷貝 10var dump ...
深入理解 引用
引用簡介 引用就是某一變數 目標 的乙個別名,對引用的操作和對變數直接操作完全相同。引用的宣告方法 型別識別符號 引用名 目標變數名 例1 int a int ra a 定義引用ra,他是變數a的引用,即別名 說明 1 在此不是求位址運算,而是起標識作用。2 型別識別符號是指目標變數的型別。3 宣告...