普通類型變量的指派與引用
- 執行個體 1
$a = "ABC" ;
$b =& $a ;
//此時$b與$a就是同一記憶體的兩個不同名字(表示同一個人),
//若使用unset($b)則隻是将$b這個變量訓示符(身份證)去掉了,
//$b所指向的記憶體還可以通路,因為有$a指向它;
//簡而言之,$a,$b就是一個人身份的證明
//而“ABC”(value值)就是實際的人
//unset($a)或unset($b)就是登出身份證明,
//當一個人所有的身份證明都被登出以後,這個人就不能被通路了。
//是以引用操作實際就是将身份證明複制一份而已,應該很好了解吧*/
echo $a ; // 這裡輸出: ABC
echo $b ; // 這裡輸出: ABC
$b = "EFG" ;
echo $a ; // 因為$a與$b指的是同一個人,是以$a的值也變為EFG
echo $b
- 執行個體 2
$a = 1 ;
$b =& $a ;
unset ( $a );
echo $b; // 輸出:1:
對象的引用(類類型的指派就是引用)
class fooclass{
public $att ;
}
$a = new fooclass();
$b = $a;
$a->att = 1;
$b->att = 2;
echo 'a obj:',($a->att),'<br>'; //2
echo 'b obj:',($b->att); //2
函數傳參時使用引用
$ b = 2
funtion change(&$a)//定義方法與c/c++中使用引用的方式類似
{
$a = 4;
}
change($b);
echo $b;//ouput:4
函數傳回引用
function & test()
static $b = 0 ; // 申明一個靜态變量
$b = $b + 1 ;
echo $b ;
return $b ;
}
$a = test(); // 這條語句會輸出 $b 的值 為1
$a = 5 ;
$a = test(); // 這條語句會輸出 $b 的值 為 2
$a =& test(); // 這條語句會輸出 $b 的值 為 3 (注意函數的定義以及調用時都要使用&操作符)
$a = 5 ;
$a = test(); // 這條語句會輸出 $b 的值 為 6
數組類型變量的指派不是引用
$arr_1 = [1,2,3];
$arr_2 = $arr_1;//在php中array與object是不同的類型,雖然對象的指派就是引用指派(在php5.0以後),數組這裡可以簡單地認為就是新開辟了一塊記憶體(深入來講,其實存在“引用計數、寫時拷貝”的機制)
$arr_2[0] = 2;
foreach ($arr_1 as $value)
{
echo "value_of_arr1=".$value."<br>";
}
foreach ($arr_2 as $value)
{
echo "value_of_arr2=".$value."<br>";
}
/*
結果如下:
value_of_arr1=1
value_of_arr1=2
value_of_arr1=3
value_of_arr2=2
value_of_arr2=2
value_of_arr2=3
*/
結論: PHP 的數組指派是 copy 而非引用,指派過程會建立新的數組賦予被指派的變量。在新變量上的數組操作并不會影響到原數組變量中的内容
引用數組中的元素,引發的” 魔法 “
- 執行個體 1
$a = array(21, 7);
$c = & $a[0];
$b = $a;
$b[0]= 1;
$b[1]=2;
var_dump($a);
echo '<br/>';
var_dump($b);
echo '<br/>';
var_dump($c);
echo '<br/>';
// Output:
/* array(2) { [0]=> &int(1) [1]=> int(7) }
array(2) { [0]=> &int(1) [1]=> int(2) }
string(2) "21"
*/
// 可以看到$a[0]與$b[0]均變為類引用類型;
- 執行個體 2(接執行個體 1)
unset($c);
var_dump($a);
echo '<br/>';
var_dump($b);
echo '<br/>';
/* Output:
array(2) { [0]=> &int(1) [1]=> int(7) }
array(2) { [0]=> &int(1) [1]=> int(2) }
*/
// 此時$a[0]與$b[0]還是類引用類型;
- 執行個體 3(接執行個體 2)
unset($a);
var_dump($b);
/* output:
array(2) { [0]=> &int(1) [1]=> int(7) }
*/
此時$b[0]還是引用類型
接下來就是見證奇迹的時刻啦--見證奇迹的時刻啦----見證奇迹的時刻啦---見證奇迹的時刻啦
但是,如果本執行個體中不是unset($a),而是unset($b),則var_dump($a);
可以看到結果:array(2) { [0]=> int(1) [1]=> int(7) }
也就是說此時$a[0]又變回正常的非引用變量了
global 操作符
<?php
$var1 = 1;
$var2 = 2;
function test1(){
$GLOBALS['var2'] = &$GLOBALS['var1'];
//$GLOBALS['var2']此時就是代表函數外$var1變量本身
}
test1();
echo $var2 . "<br />";
$var3 = 1;
$var4 = 2;
function test2(){
global $var3;//重點:相當于$var3=& $GLOBALS['var3'];
global $var4;
$var4 = &$var3;
}
test2();
echo $var4 . "<br />";
?>
- 執行個體 2
$var1 = 1;
function test1(){
unset($GLOBALS['var1']);
}
test1();
echo $var1 . "<br />";//輸出:Notice: Undefined variable: var1
$var2 = 1;
function test2(){
global $var2;
unset($var2);
}
test2();
echo $var2;//輸出1
?>
/*結果:undefined variable 與1
由此可證明global $a;就等價于$a = & $GLOBALS['a'];
總結
- 引用操作就是給記憶體取别名(或者說是給一個人多弄一個身份證明)
-
global 操作其實是偷偷使用了引用操作:
global $a; 等價于 $a = & $GLOBALS['a']
- 要想函數傳回引用,需要都定義函數以及調用函數時,都使用 & 操作符;否則函數傳回的不是引用
牛刀小試
$var1 = "Example variable";
$var2 = "";
function global_references($use_globals)
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; // $var2隻在該函數内有效
} else {
$GLOBALS["var2"] =& $var1;
}
}
global_references(false);
echo "var2 is set to'$var2'", '<br>'; // var2被設定為 ''
global_references(true);
echo "var2 is set to'$var2'"; // var2被設定為'Example variable' //通過該例子可以進一步鞏固我們所學的知識,聰明的你掌握了沒