天天看点

PHP引用与global操作符

普通类型变量的赋值与引用

  • 实例 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'  //通过该例子可以进一步巩固我们所学的知识,聪明的你掌握了没      

继续阅读