一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

PHP引用(&)各種使用方法實(shí)例詳解

php的引用(就是在變量或者函數(shù)、對象等前面加上&符號),在php 中引用的意思是:不同的名字訪問同一個(gè)變量內(nèi)容。與C語言中的指針是有差別的.C語言中的指針里面存儲的是變量的內(nèi)容,在內(nèi)存中存放的地址。

1.變量的引用
php 的引用允許你用兩個(gè)變量來指向同一個(gè)內(nèi)容
復(fù)制代碼 代碼如下:<?
    $a="ABC";
    $b =&$a;
    echo $a;//這里輸出:ABC
    echo $b;//這里輸出:ABC
    $b="EFG";
    echo $a;//這里$a的值變?yōu)镋FG 所以輸出EFG
    echo $b;//這里輸出EFG
?>

2.函數(shù)的引用傳遞(傳址調(diào)用)
傳址調(diào)用我就不多說了 下面直接給出代碼
復(fù)制代碼 代碼如下:<?php

    function test(&$a)
    {
        $a=$a+100;
    }
    $b=1;
    echo $b;//輸出1
    test($b);   //這里$b傳遞給函數(shù)的其實(shí)是$b的變量內(nèi)容所處的內(nèi)存地址,通過在函數(shù)里改變$a的值 就可以改變$b的值了
    echo "<br>";
    echo $b;//輸出101
?>

要注意的是,在這里test(1);的話就會出錯(cuò),原因自己去想。
注意:上面的“ test($b); ” 中的$b前面不要加 & 符號,但是在函數(shù)“call_user_func_array”中,若要引用傳參,就得需要 & 符號,如下代碼所示:
復(fù)制代碼 代碼如下:<?php
function a(&$b){
    $b++;
}
$c=0;
call_user_func_array('a',array(&$c));
echo $c;
//輸出 1
?>
3.函數(shù)的引用返回
先看代碼

復(fù)制代碼 代碼如下:<?php
function &test()
{
    static $b=0;//申明一個(gè)靜態(tài)變量
    $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
?>

下面解釋下: 
通過這種方式$a=test();得到的其實(shí)不是函數(shù)的引用返回,這跟普通的函數(shù)調(diào)用沒有區(qū)別 至于原因: 這是php的規(guī)定
php規(guī)定通過$a=&test(); 方式得到的才是函數(shù)的引用返回
至于什么是引用返回呢(php手冊上說:引用返回用在當(dāng)想用函數(shù)找到引用應(yīng)該被綁定在哪一個(gè)變量上面時(shí)。) 這句狗屁話 害我半天沒看懂

用上面的例子來解釋就是
$a=test()方式調(diào)用函數(shù),只是將函數(shù)的值賦給$a而已, 而$a做任何改變 都不會影響到函數(shù)中的$b
而通過$a=&test()方式調(diào)用函數(shù)呢, 他的作用是 將return $b中的 $b變量的內(nèi)存地址與$a變量的內(nèi)存地址 指向了同一個(gè)地方
即產(chǎn)生了相當(dāng)于這樣的效果($a=&$b;) 所以改變$a的值 也同時(shí)改變了$b的值 所以在執(zhí)行了
$a=&test();
$a=5;
以后,$b的值變?yōu)榱?

這里是為了讓大家理解函數(shù)的引用返回才使用靜態(tài)變量的,其實(shí)函數(shù)的引用返回多用在對象中

另附一個(gè)php官方例子:
復(fù)制代碼 代碼如下:This is the way how we use pointer to access variable inside the class.
<?php
class talker{
    private $data = 'Hi';
    public function & get(){
        return $this->data;
    }

    public function out(){
        echo $this->data;
    }  
}
$aa = new talker();
$d = &$aa->get();
$aa->out();
$d = 'How';
$aa->out();
$d = 'Are';
$aa->out();
$d = 'You';
$aa->out();
?>
//the output is "HiHowAreYou"

4.對象的引用
復(fù)制代碼 代碼如下:<?php
    class a{
        var $abc="ABC";
    }
    $b=new a;
    $c=$b;
    echo $b->abc;//這里輸出ABC
    echo $c->abc;//這里輸出ABC
    $b->abc="DEF";
    echo $c->abc;//這里輸出DEF
?>

上代碼是在php5中的運(yùn)行效果

php5中 對象的賦值是個(gè)引用的過程。上列中$b=new a; $c=$b; 其實(shí)等效于$b=new a; $c=&$b;
php5中默認(rèn)就是通過引用來調(diào)用對象, 但有時(shí)你可能想建立一個(gè)對象的副本,并希望原來的對象的改變不影響到副本 . 為了這樣的目的,php5定義了一個(gè)特殊的方法,稱為__clone。
php 5 起,new 自動(dòng)返回引用,因此在此使用 =& 已經(jīng)過時(shí)了并且會產(chǎn)生 E_STRICT 級別的消息。
php4中,對象的賦值是個(gè)拷貝過程,
如:$b=new a,其中new a產(chǎn)生的是一個(gè)匿名的a對象實(shí)例,而此時(shí)的$b是對這個(gè)匿名對象的拷貝。同理$c=$b,也是對$b內(nèi)容的一個(gè)拷貝。所以在php4中,為了節(jié)省內(nèi)存空間,$b=new a 一般會改成引用的模式,即 $b=& new a。

下面再來個(gè) 官方 提供的例子:
php5中,你不需要額外添加什么東西就可到達(dá)“對象引用”的功能:
復(fù)制代碼 代碼如下:<?php
class foo{
        protected $name;
        function __construct($str){
                $this->name = $str;
        }
        function __toString(){
                return  'my name is "'. $this->name .'" and I live in "' . __CLASS__ . '".' . "/n";
        }
        function setName($str){
                $this->name = $str;
        }
}
class MasterOne{
        protected $foo;
        function __construct($f){
                $this->foo = $f;
        }
        function __toString(){
                return 'Master: ' . __CLASS__ . ' | foo: ' . $this->foo . "/n";
        }
        function setFooName($str){
                $this->foo->setName( $str );
        }
}
class MasterTwo{
        protected $foo;
        function __construct($f){
                $this->foo = $f;
        }
        function __toString(){
                return 'Master: ' . __CLASS__ . ' | foo: ' . $this->foo . "/n";
        }
        function setFooName($str){
                $this->foo->setName( $str );
        }
}
$bar = new foo('bar');
print("/n");
print("Only Created /$bar and printing /$bar/n");
print( $bar );
print("/n");
print("Now /$baz is referenced to /$bar and printing /$bar and /$baz/n");

$baz =& $bar;
print( $bar );
print("/n");
print("Now Creating MasterOne and Two and passing /$bar to both constructors/n");

$m1 = new MasterOne( $bar );
$m2 = new MasterTwo( $bar );
print( $m1 );
print( $m2 );
print("/n");
print("Now changing value of /$bar and printing /$bar and /$baz/n");

$bar->setName('baz');
print( $bar );
print( $baz );
print("/n");
print("Now printing again MasterOne and Two/n");
print( $m1 );
print( $m2 );
print("/n");
print("Now changing MasterTwo's foo name and printing again MasterOne and Two/n");

$m2->setFooName( 'MasterTwo/'s Foo' );
print( $m1 );
print( $m2 );
print("Also printing /$bar and /$baz/n");
print( $bar );
print( $baz );
?>

輸出:
復(fù)制代碼 代碼如下:Only Created $bar and printing $bar
my name is "bar" and I live in "foo".
Now $baz is referenced to $bar and printing $bar and $baz
my name is "bar" and I live in "foo".
Now Creating MasterOne and Two and passing $bar to both constructors
Master: MasterOne | foo: my name is "bar" and I live in "foo".
Master: MasterTwo | foo: my name is "bar" and I live in "foo".
Now changing value of $bar and printing $bar and $baz
my name is "baz" and I live in "foo".
my name is "baz" and I live in "foo".
Now printing again MasterOne and Two
Master: MasterOne | foo: my name is "baz" and I live in "foo".
Master: MasterTwo | foo: my name is "baz" and I live in "foo".
Now changing MasterTwo's foo name and printing again MasterOne and Two
Master: MasterOne | foo: my name is "MasterTwo's Foo" and I live in "foo".
Master: MasterTwo | foo: my name is "MasterTwo's Foo" and I live in "foo".
Also printing $bar and $baz
my name is "MasterTwo's Foo" and I live in "foo".
my name is "MasterTwo's Foo" and I live in "foo".


上個(gè)例子解析:
復(fù)制代碼 代碼如下:$bar = new foo('bar');
$m1 = new MasterOne( $bar );
$m2 = new MasterTwo( $bar );

實(shí)例對象$m1與$m2中的$bar是對實(shí)例$bar的引用,而非拷貝,這是php5中,對象引用的特點(diǎn),也就是說
1.$m1或$m2內(nèi)部,任何對$bar的操作都會影響外部對象實(shí)例$bar的相關(guān)值。
2.外部對象實(shí)例$bar的改變也會影響$m1和$m2內(nèi)部的$bar的引用相關(guān)值。

php4中,要實(shí)現(xiàn)如上述的 用一個(gè)對象實(shí)例去當(dāng)著另外一個(gè)對象的屬性時(shí),其等價(jià)代碼(即引用調(diào)用)類似如下:
復(fù)制代碼 代碼如下:class foo{
   var $bar;
   function setBar(&$newBar){
      $this->bar =& newBar;
   }
}

5.引用的作用
如果程序比較大,引用同一個(gè)對象的變量比較多,并且希望用完該對象后手工清除它,個(gè)人建議用 "&" 方式,然后用$var=null的方式清除. 其它時(shí)候還是用php5的默認(rèn)方式吧. 另外, php5中對于大數(shù)組的傳遞,建議用 "&" 方式, 畢竟節(jié)省內(nèi)存空間使用。
6.取消引用
當(dāng)你 unset 一個(gè)引用,只是斷開了變量名和變量內(nèi)容之間的綁定。這并不意味著變量內(nèi)容被銷毀了。例如:
復(fù)制代碼 代碼如下:
<?php
    $a = 1;
    $b =& $a;
    unset ($a);
?>
不會 unset $b,只是 $a。
7.global 引用
當(dāng)用 global $var 聲明一個(gè)變量時(shí)實(shí)際上建立了一個(gè)到全局變量的引用。也就是說和這樣做是相同的:
<?php
    $var =& $GLOBALS["var"];
?> 
這意味著,例如,unset $var 不會 unset 全局變量。
如果在一個(gè)函數(shù)內(nèi)部給一個(gè)聲明為 global 的變量賦于一個(gè)引用,該引用只在函數(shù)內(nèi)部可見??梢酝ㄟ^使用 $GLOBALS 數(shù)組避免這一點(diǎn)。
Example  在函數(shù)內(nèi)引用全局變量

復(fù)制代碼 代碼如下:<?php
$var1 = "Example variable";
$var2 = "";
function global_references($use_globals)
{
    global $var1, $var2;
    if (!$use_globals) {
        $var2 =& $var1; // visible only inside the function
    } else {
        $GLOBALS["var2"] =& $var1; // visible also in global context
    }
}
global_references(false);
echo "var2 is set to '$var2'/n"; // var2 is set to ''
global_references(true);
echo "var2 is set to '$var2'/n"; // var2 is set to 'Example variable'
?>

把 global $var; 當(dāng)成是 $var =& $GLOBALS['var']; 的簡寫。從而將其它引用賦給 $var 只改變了本地變量的引用。

8.$this
在一個(gè)對象的方法中,$this 永遠(yuǎn)是調(diào)用它的對象的引用。
//下面再來個(gè)小插曲
php中對于地址的指向(類似指針)功能不是由用戶自己來實(shí)現(xiàn)的,是由Zend核心實(shí)現(xiàn)的,php中引用采用的是“寫時(shí)拷貝”的原理,就是除非發(fā)生寫操作,指向同一個(gè)地址的變量或者對象是不會被拷貝的。
通俗的講
1:如果有下面的代碼
[code]<?
    $a="ABC";
    $b=&$a;
?>

其實(shí)此時(shí) $a與$b都是指向同一內(nèi)存地址 而并不是$a與$b占用不同的內(nèi)存
2:如果在上面的代碼基礎(chǔ)上再加上如下代碼
復(fù)制代碼 代碼如下:<?php
  $a="EFG";
?>

由于$a與$b所指向的內(nèi)存的數(shù)據(jù)要重新寫一次了,此時(shí)Zend核心會自動(dòng)判斷 自動(dòng)為$b生產(chǎn)一個(gè)$a的數(shù)據(jù)拷貝,重新申請一塊內(nèi)存進(jìn)行存儲
php的引用(就是在變量或者函數(shù)、對象等前面加上&符號)是個(gè)高級話題,新手多注意,正確的理解php的引用很重要,對性能有較大影響,而且理解錯(cuò)誤可能導(dǎo)致程序錯(cuò)誤!
很 多人誤解php中的引用跟C當(dāng)中的指針一樣,事實(shí)上并非如此,而且很大差別。C語言中的指針除了在數(shù)組傳遞過程中不用顯式申明外,其他都需要使用*進(jìn)行定 義,而php中對于地址的指向(類似指針)功能不是由用戶自己來實(shí)現(xiàn)的,是由Zend核心實(shí)現(xiàn)的,php中引用采用的是“寫時(shí)拷貝”的原理,就是除非發(fā)生 寫操作,指向同一個(gè)地址的變量或者對象是不會被拷貝的,比如下面的代碼:
復(fù)制代碼 代碼如下:$a = array('a','c'...'n');
$b = $a;
如果程序僅執(zhí)行到這里,$a和$b是相同的,但是并沒有像C那樣,$a和$b占用不同的內(nèi)存空間,而是指向了同一塊內(nèi)存,這就是php和c的差別,并不需要 寫成$b=&$a才表示$b指向$a的內(nèi)存,zend就已經(jīng)幫你實(shí)現(xiàn)了引用,并且zend會非常智能的幫你去判斷什么時(shí)候該這樣處理,什么時(shí)候不 該這樣處理。
如果在后面繼續(xù)寫如下代碼,增加一個(gè)函數(shù),通過引用的方式傳遞參數(shù),并打印輸出數(shù)組大小。
復(fù)制代碼 代碼如下:function printArray(&$arr) //引用傳遞
{
   print(count($arr));

}
printArray($a);
上面的代碼中,我們通過引用把$a數(shù)組傳入printArray()函數(shù),zend引擎會認(rèn)為printArray()可能會導(dǎo)致對$a的改變,此時(shí)就會自動(dòng)為$b生產(chǎn)一個(gè)$a的數(shù)據(jù)拷貝,重新申請一塊內(nèi)存進(jìn)行存儲。這就是前面提到的“寫時(shí)拷貝”概念。
如果我們把上面的代碼改成下面這樣:
復(fù)制代碼 代碼如下:function printArray($arr)   //值傳遞
{
   print(count($arr));
}
printArray($a);

上面的代碼直接傳遞$a值到printArray()中,此時(shí)并不存在引用傳遞,所以沒有出現(xiàn)寫時(shí)拷貝。
大家可以測試一下上面兩行代碼的執(zhí)行效率,比如外面加入一個(gè)循環(huán)1000次,看看運(yùn)行的耗時(shí),結(jié)果會讓你知道不正確使用引用會導(dǎo)致性能下降30%以上。
自我理解:按傳值的話是與函數(shù)內(nèi)的參數(shù)無關(guān),相當(dāng)于局部變量的作用,而按傳址(引用)的話卻與函數(shù)內(nèi)的參數(shù)有關(guān),相當(dāng)于全局變量的作用.而從性能方面來說,看上面分析就夠..

 

php技術(shù)PHP引用(&amp;)各種使用方法實(shí)例詳解,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 亚洲综合偷自成人网第页色 | 人人洗澡人人洗澡人人 | 久久tv| 97碰视频人人做人人爱欧美 | 成人激情小视频 | 91精品免费国产高清在线 | 97视频在线观看视频在线精品 | 亚洲福利在线看 | 久久久精品2018免费观看 | 国产成人亚洲精品 | 91麻豆精品激情在线观看最新 | 中文字幕在线观看一区 | 91精品小视频| 婷婷网五月天天综合天天爱 | 国产成人免费午夜在线观看 | 91麻豆麻豆 | 色网站免费观看 | 99re6这里只有精品视频 | 伊人精品在线视频 | 亚洲 激情 | 91香蕉福利一区二区三区 | 婷婷草| 激情五月激情 | 国产男女免费完整视频 | 中文字幕第一页在线视频 | 国产大片91精品免费看3 | 日本韩国一级 | 激情小视频在线观看 | 在线观看91精品国产不卡免费 | 国产综合视频在线观看一区 | 涩涩涩视频在线观看免费 | 99亚洲精品 | 亚洲日本1区2区3区二区 | 成年女人免费v片 | 九九视频网站 | 亚洲区欧美区小说区图片区 | 国产成人免费 | 91精品欧美一区二区三区 | 欧美人体大胆做受 | 国产极品在线观看 | 国产精品玖玖 |