一:引用&概念

在PHP 中引用的意思是:用不同的名字访问同一个变量内容.
定义方式& (读”and”的音,@读“爱特”)

二:赋值方式

  1. 1。“=”:是值复制,把右边表达式的值赋给左边的运算数。它将右边表达式值复制一份,交给左边的运算数,此时还是共享一块内存地址。当其中任何一个值发生更改的时候,再分配不同的内存地址。见下面写时拷贝<br /> 2。“=&”:是引用赋值,就是公用一个存储单元。如果这个内存存储的数据变了,那么两个变量的值都会发生变化。<br />

三:写时拷贝

1 解释:

PHP有一个机制,叫做cow (Copy On Write),写时拷贝
$b = $a;此时还是指向的一个内存地址,当我们对$a和$b其中一个变量进行修改操作的时候,才会发生copy操作,即给$b也复制一块内存地址 。

2 =方式:

1 如果有下面的代码

$a = range(0, 1000); 
$b = $a;

其实此时 $a与$b都是指向同一内存地址 而并不是$a与$b占用不同的内存
=&引用赋值  ,=值赋值,  写时拷贝 - 图1
2 此时给$a重新赋值:
$a = range(0, 1000);
由于$a发生了改变,此时Zend核心会自动判断,$a变化了,为$a重新申请一块内存地址进行存储新的值,$b未发生改变,所以$b仍然指向原先的内存地址。
=&引用赋值  ,=值赋值,  写时拷贝 - 图2

3 &方式

如果$b引用$a的值,$a变化前后,$b和$a都是指向一块内存地址。修改$a只是将内存地址的值修改了。

$a = range(0, 1000);
$b = &$a;
$a = range(0, 1000);


=&引用赋值  ,=值赋值,  写时拷贝 - 图3

4 优点:

普通值赋值,也就是=,采用写时拷贝的方式,会节约内存使用,

5 用=还是&:

如果只是想复制一个值,对该值得操作不影响原先的值,那么就用=的方式
对于大数组的传递,或者想改变原先的值,就用引用

四:引用的三种方法

1 &符号引用

$b = &$a;
这两个变量现在共享一个内存的存储区域,就是说它们的值是一样的

2 global 引用

global 引用 当用 global $var 声明一个变量时实际上建立了一个到全局变量的引用
也就是说和这样做是相同的:

<?php
$var =& $GLOBALS["var"];

3 $this的用法

在一个对象的方法中,$this 永远是调用它的对象的引用。

五:php中的引用和c中的指针区别

很多人误解php中的引用跟C当中的指针一样,事实上并非如此,而且很大差别。
C语言中的指针除了在数组传递过程中不用显式申明外,其他都需要使用*进行定义,
而php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,
php中引用采用的是“写时拷贝”的原理,就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的。

六:引用用法

1 变量中使用引用&

php默认为传值传递:

<?php   
$a = 20;
$b = $a;
$a = $a + 10;
echo $a.' and '.$b;

程序运行结果:
30 and 20

地址传递需要加&

<?php
$a = 20;
$b = &$a;
$a = $a + 10;
echo $a.' and '.$b;

程序运行结果:
30 and 30

结论:

&把$a的地址传给了$b,这样的话这两个变量现在共享一个内存的存储区域,这两个变量更改任何一个,另一个都会改变。

2 函数的传址调用

函数传参默认是通过传值的方式,相当于是复制了一份该参数的值,将复制的值当做参数传递。采用引用的方式,就是传址传递,是将该参数的内存地址传进去的。
参数的引用用处:一个是节省内存空间,一个是函数内部对参数的修改,会直接修改外部的值。
注意:参数使用引用,调用该参数的时候只能传递变量!

<?php
function test(&$a){ 
    $a=$a+100; 
} 
$b=1; 
echo $b;//输出1 
test($b);   //这里$b传递给函数的其实是$b的变量内容所处的内存地址,通过在函数里改变$a的值 就可以改变$b的值了 
echo "<br>"; 
echo $b;//输出101

要注意的是,在这里test(1);的话就会出错,原因是:PHP规定传递的引用不能为常量(可以看错误提示)。

3 函数的引用返回

引用返回用在 当想用函数找到引用应该被绑定在哪一个变量上面时
和参数传递不同,引用返回必须在申明函数和调用函数的地方都用 & 符号——指出函数返回的是一个引用,而不是通常的一个拷贝,同样也指出 引用调用函数是作为引用的绑定,而不是通常的赋值(引用调用函数的变量和函数的返回值共享一个内存地址)

<?php
function &test(){
    static $b=0;//申明一个静态变量 
    $b=$b+1; 
    echo $b; 
    return $b; 
}
$a=test();//1 将函数返回的$b的值赋值给$a
$a=5; 
$a=test();//2 将函数返回的$b的值赋值给$a
$a=&test();//3 将函数返回的$b和$a共用一个内存空间,相当于 $a=&$b
$a=5; 
$a=test();//6 上面将$a赋值为5,所以$b也等于5,$b是静态变量,只初始化一次,$b+1,此时为6

解释:

$a=test()方式调用函数,只是将函数的值赋给$a而已,而$a做任何改变,不会影响到函数中的$b,此时的function &test()有没有&是没有区别的
而通过$a=&test()方式调用函数呢, 他的作用是 将return $b中的 $b变量的内存地址与$a变量的内存地址 指向了同一个地方 即产生了相当于这样的效果($a=&b;) 所以改变$a的值 也同时改变了$b的值 所以在执行了 $a=&test(); $a=5; 以后,$b的值变为了5。function &test()中也必须写引用。

4 对象的引用

<?php
class a{
    public $abc="ABC";
} 
$b=new a; 
$c=$b; 
echo $b->abc;//这里输出ABC 
echo $c->abc;//这里输出ABC 
$b->abc="DEF"; 
echo $c->abc;//这里输出DEF

PHP5中默认就是通过引用来调用对象,(引用的是对象的标识符(一个ID),这个标识符指向对象本身)
但有时你可能想建立一个对象的副本,并希望原来的对象的改变不影响到副本 . 为了这样的目的,PHP定义了一个特殊的方法,称为clone.
[PHP中的对象复制及
clone() 函数](https://www.yuque.com/go/doc/11121303?view=doc_embed)

七:引用的作用

采用引用的方式,一个是节省内存空间,一个是函数内部对参数的修改,会直接修改外部的值。
如果程序比较大,引用同一个对象的变量比较多,并且希望用完该对象后手工清除它,建议用 “&” 方式,然后用$var=null的方式清除.
对于大数组的传递,建议用 “&” 方式, 节省内存空间使用。

函数中大的变量,如数组可以采用引用的方式如:

<?php
$categories = array(
    array('id'=>1,'name'=>'电脑','pid'=>0),
    array('id'=>2,'name'=>'手机','pid'=>0),
);
function abc(&$categories){
    //forech中并不需要使用&,因为foreach没有自己的作用域,可以直接使用同一个作用域中的变量。function有作用域,
    foreach ($categories as $key => $value) {
        unset($categories[$key]);
    }
}
echo '<pre>';
    print_r($categories);//abc函数内部unset了数组的键,外部的数组也会发生改变
echo '</pre>';



对象类的传递默认是引用

<?php
class qw
{
    public $a = array(1,2,3);
    public $ab = array(11,22,33);
}
$categories = new qw();
$a = abc($categories);

// abc($categories)不加引用也可以,默认就是通过引用的方式传递对象
function abc($categories){
    foreach ($categories as $key => $value) {
        unset($categories->$key);
    }
}
echo '<pre>';
    print_r($categories);//空对象。
echo '</pre>';

八:取消引用

当你 unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了,只会删除这个变量。例如:

<?Php
<?php 
$a = 1; 
$b =&$a; 
unset ($a); 
?>
//不会 unset $b,只是 $a。 
function quoteTest(){ 
    global $var ; //相当于 $var = &$GLOBALS['var']; 
    unset($var); //删除只是删除引用,而引用的内容还存在,同上这并不意味着变量内容被销毁了
}
$var=1;
quoteTest();
echo $var; //  结果 1


$var=null的方式清除内容