PHP 引用

alansleep發表於2013-02-05

php的引用與c++引用有點差距.比如返回引用時不用考慮區域性變數的作用域,外部接收函式返回時需要顯示的加上&號,以表示是引用返回而不是拷貝返回.這就像要兩頭商量一樣.
php的引用在定義後,甚至不用定義,在後續使用時可以隨時修改引用的目標.而c++的引用變數在初始化後就不能修改為別的引用了.
引用變數:

$a = 1;
$b = 2;
$c = 3;

$a = &$b;
echo $a.' '.$b.'<br/>';    
$a = &$c;
echo $a.' '.$b.'<br/>';

官方說明說通過&號,$a指向了$b同一個地方.但我覺得c++引用的概念, $a是$b的別名也講的通.操作$a和操作$b一樣.互相都體現變化.
如上面說的,php引用可以隨時更換目標.
引用引數:
在函式的引數前面加上&號表示該引數會以引用方式傳入.函式內部對引數修改會影響到實參.

 $arr = array(1,2,3,4,5);

function fun(&$p)
{  
    if(is_array($p))
    {
        foreach($p as &$v)
        {
            ++$v;
        }
        var_dump($p);
        echo '<br/><br/>';
    }

}
fun($arr);
var_dump($arr);

在呼叫時不用fun(&$arr)來表示引用傳入,最新的php版本會對此報錯.
程式碼輸最後dump的輸出顯示$arr被函式內部修改.

甚至不需要預先定義變數:

function foo(&$var) { }

foo($a); // $a is "created" and assigned to null

$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)

$c = new StdClass; // new已經能給編譯器表示是引用返回,所以舊的$c =& new StdClass會報錯.
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)   

如果對一個未定義的變數進行引用賦值、引用引數傳遞或引用返回,則會自動建立該變數.
global總是那麼難纏:
在一個函式內將一個全域性變數申明為global,之後對他進行引用指向後的操作僅在函式內有效.

$var1 = "Example variable";
$var2 = "";
function global_references($use_globals)
{
    global $var1, $var2;
    if (!$use_globals) {
        $var2 =& $var1; // visible only inside the function
        echo 'false    '.$var2.'<br/>';
    } else {
        $GLOBALS["var2"] =& $var1; // visible also in global context
        echo 'true     '.$GLOBALS["var2"].'<br/>';
    }
}
global_references(false);
echo '$var2 = '.$var2.'<br/>';
global_references(true);
echo '$var2 = '.$var2.'<br/>';
$var2 = 1;
echo '$var1 = '.$var1.'<br/>';  

輸出:
false Example variable
$var2 =
true Example variable
$var2 = Example variable
$var1 = 1
雖然有$GLOBALS['var2']的方法解決.但是多彆扭啊. 直接在引數裡傳個引用引數就得了.

foreach的as:
也可以是這樣引用來修改陣列value

$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
    // do something
}
echo $ref; // 3 - last element of the iterated array 

和最上面的foreach其實是一樣啦.
引用返回:
函式名前面加上 & 表示返回引用.

function &funref(& $p)
{
    $p = 'funref'.' hei<br/>';
    return $p;
}
$refrst = &funref($ref);
echo '<br/> '.$ref.'   '.$refrst.'<br/>';
$ref = 'abc';
echo '<br/> '.$ref.'   '.$refrst.'<br/>'; 

變數$ref為自動建立.在函式內被修改值後返回引用,在$refrst接收引用時需要在賦值表示式加上&表示為引用方式接收返回.
如果不加的話,那$refrst為函式返回值的一個拷貝.可以通過後面的$ref修改來發現,$refrst的值不隨之改變.
引用的引用實際還是最初的物件的引用:

function refsref()
{
    $var = 'string';
    $ref =& $var;
    $refref =& $ref;

    echo $ref.'  '.$refref.'<br/>';
    $ref = 'strinttt';
    echo $ref.'  '.$refref.'<br/>';
    unset($ref);
    echo '  '.$refref.'<br/>';
}
refsref();   

同發於我的部落格:EPICS.CN

相關文章