一:引用&概念
在PHP 中引用的意思是:用不同的名字访问同一个变量内容.
定义方式& (读”and”的音,@读“爱特”)
二:赋值方式
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占用不同的内存
2 此时给$a重新赋值:
$a = range(0, 1000);
由于$a发生了改变,此时Zend核心会自动判断,$a变化了,为$a重新申请一块内存地址进行存储新的值,$b未发生改变,所以$b仍然指向原先的内存地址。
3 &方式
如果$b引用$a的值,$a变化前后,$b和$a都是指向一块内存地址。修改$a只是将内存地址的值修改了。
$a = range(0, 1000);
$b = &$a;
$a = range(0, 1000);
4 优点:
5 用=还是&:
如果只是想复制一个值,对该值得操作不影响原先的值,那么就用=的方式
对于大数组的传递,或者想改变原先的值,就用引用
四:引用的三种方法
1 &符号引用
$b = &$a;
这两个变量现在共享一个内存的存储区域,就是说它们的值是一样的
2 global 引用
global 引用 当用 global $var 声明一个变量时实际上建立了一个到全局变量的引用
也就是说和这样做是相同的:
<?php
$var =& $GLOBALS["var"];
3 $this的用法
五:php中的引用和c中的指针区别
很多人误解php中的引用跟C当中的指针一样,事实上并非如此,而且很大差别。
C语言中的指针除了在数组传递过程中不用显式申明外,其他都需要使用*进行定义,
而php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,
php中引用采用的是“写时拷贝”的原理,就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的。
六:引用用法
1 变量中使用引用&
php默认为传值传递:
<?php
$a = 20;
$b = $a;
$a = $a + 10;
echo $a.' and '.$b;
地址传递需要加&
<?php
$a = 20;
$b = &$a;
$a = $a + 10;
echo $a.' and '.$b;
结论:
&把$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的方式清除内容