php中传值与传引用有什么不同

小编给大家分享一下php中传值与传引用有什么不同,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

成都创新互联主营蓟州网站建设的网络公司,主营网站建设方案,app软件开发公司,蓟州h5成都小程序开发搭建,蓟州网站营销推广欢迎蓟州等地区企业咨询

传值是将变量的值复制出一份新的值;在函数范围内,改变变量值得大小,不会影响到函数外边的变量值。传引用是将变量的引用复制出来一份;在函数范围内,对值的任何改变,在函数外部也有所体现,因为传引用传的是内存地址。

php传值:在函数范围内,改变变量值得大小,都不不会影响到函数外边的变量值。

PHP按引用:在函数范围内,对值的任何改变,在函数外部也有所体现,因为传引用传的是内存地址。

传值和传引用、传地址的区别:

1、传值,是把实参的值赋值给行参

那么对行参的修改,不会影响实参的值

2、传地址

是传值的一种特殊方式,只是他传递的是地址,不是普通的如int

那么传地址以后,实参和行参都指向同一个对象

3、传引用

真正的以地址的方式传递参数

传递以后,行参和实参都是同一个对象,只是他们名字不同而已

对行参的修改将影响实参的值

大牛的解释:

传值:和copy是一样的。【打个比方,我有一橦房子,我给你建筑材料,你建了一个根我的房子一模一样的房子,你在你的房子做什么事都不会影响到我,我在我的房子里做什么事也不会影响到你,彼此独立。】

传引用:类似于C语言的指针了,感觉差不多。打个比方,我有一橦房子,我给你一把钥匙,我们二个都可以进入这个房子,你在房子做什么都会影响到我。

【优缺点:】传值会很耗时间,特别是对于大型的字符串和对象来说,这将会是一个代价很大的操作,传送引用,函数内的任何操作等同于对传送变量的操作,传送大型变量时效率高!

1.先来解释一下名词。

值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的。

注意:上面红字部分说明,应用传递不是不开辟空间,是开辟空间的,只不过开辟的空间是用来存放实参变量地址的。

2.php中引用的用法有以下三种。

①. 变量的引用赋值: $a = &$b

②. 函数调用时的引用参数传递

1) 早期php是在调用时通过&符号传递引用类型的变量, 比如: func(&$arg);

2) 后来, 函数的引用类型参数被规定为需要在函数声明时定义, 不如: function func(&$arg);

注意:引用声明时定义引用类型参数后,运行时引用参数传递被废弃,需要在php.ini中增加allow_call_time_pass_reference来开启.

③. 函数返回引用类型,这种应用方式需要声明函数时,在函数名前增加&符号,并且,在调用时,要用引用赋值方式, 实例代码如下:

function &func() {
    return $a;
}
$a = func();  //这种调用方式得到的不是引用传值
$a =& func(); //这样调用才是引用传值
$a = 1;
function &func(&$a) {
  return $a;
}
$b = func($a);
$c =& func($a);
$b = 2;
echo "a: $a, b: $b, c: $c. 
/n"; //输出a: 1, b: 2, c: 1. //可见对$b的修改不会影响$a $c = 3; echo "a: $a, b: $b, c: $c.
/n"; //输出a: 3, b: 2, c: 3. //可见对$c的修改会影响$a

请看下面详细的例子:

3.php各种数据类型传值/指针

一、基本数据类型的传值

/* **************************************************** */ 
function testvar($k){
 $k = 40;
}
$c = 30;
//给一个函数参数传一个基本数据类型(整型,布尔,字符 ...), 实际上传的就是值 ;
testvar($c);
echo $c;//结果是:30
function testvar2(&$k){
 $k = 40;
}
$e = 30;
//给一个函数参数传一个基本数据类型(整型,布尔,字符 ...), 实际上传的y就是地址 ;
testvar2($e);
echo $e;//结果是:40
  
/* **************************************************** */

二、数组(默认情况下是复制一份数据),如要传地址则&$arr

 1 $arr1 = array(-1,5,0); 
 2 function testArr($arr){ 
 3  for($i=0;$i$arr[$j]){ 
 6     $temp = $arr[$i]; 
 7     $arr[$i] = $arr[$j]; 
 8     $arr[$j] = $temp; 
 9    } 
10   } 
11  
12  } 
13  print_r($arr);  //结果:Array ( [0] => -1 [1] => 0 [2] => 5 )  
14 } 
15 testArr($arr1); 
16 print_r($arr1);  //结果:Array ( [0] => -1 [1] => 5 [2] => 0 )  
17  
18 function testArr2(&$arr){ 
19  for($i=0;$i$arr[$j]){ 
22     $temp = $arr[$i]; 
23     $arr[$i] = $arr[$j]; 
24     $arr[$j] = $temp; 
25    } 
26   } 
27  
28  } 
29 } 
30 testArr($arr1); 
31 print_r($arr1);  //结果:Array ( [0] => -1 [1] => 0 [2] => 5 )

三、对象数据类型传值

class person{
 public $name;
 public  $age;
}
  
$a = new person();
$a->name = '小明';
$a->age = '20';
//变量a在存的是对象的地址,把a赋给b这个变量,实际上就是赋了一个地址。
$b = $a;
$b->age = 30;
//echo $a->age.$b->age;//结果是:30 30
//给一个函数参数传一个对象, 实际上传的是这个对象的地址;
function test($k){
 $k->age =40;
}
//调用
test($b);
//echo $a->age.$b->age;//结果是:40 40

在PHP5中 对象的复制 是通过引用来实现的。上列中$a=new person; $b=$a; 其实等效于$a=new person; $b=&$a;
PHP5中默认就是通过引用来调用对象, 但有时你可能想建立一个对象的副本,并希望原来的对象的改变不影响到副本 . 为了这样的目的,PHP定义了一个特殊的方法,称为__clone.

4.php写时拷贝

php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,php中引用采用的是“写时拷贝”的原理,就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的。

通俗的讲

1:如果有下面的代码

$a="ABC";
 $b=$a;

其实此时$a与$b都是指向同一内存地址而并不是$a与$b占用不同的内存

2:如果在上面的代码基础上再加上如下代码

$a="EFG";

由于$a与$b所指向的内存的数据要重新写一次了,此时Zend核心会自动判断自动为$b生产一个$a的数据拷贝,重新申请一块内存进行存储。

5.php引用于C指针的区别

在PHP 中引用的意思是:不同的名字访问同一个变量内容.
与C语言中的指针是有差别的.C语言中的指针里面存储的是变量的内容在内存中存放的地址。

PHP 的引用允许你用两个变量来指向同一个内容

$a="ABC";
$b =&$a;
echo $a;//这里输出:ABC
echo $b;//这里输出:ABC
$b="EFG";
echo $a;//这里$a的值变为EFG 所以输出EFG
echo $b;//这里输出EFG

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

unset($a);
echo $b;//这里输出EFG

以上是php中传值与传引用有什么不同的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注创新互联行业资讯频道!


分享名称:php中传值与传引用有什么不同
URL网址:http://pwwzsj.com/article/jgdpdp.html