博客摘自  奔跑的大白,网址: http://www.cnblogs.com/gauze/p/5568867.html

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来开启.

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

1
2
3
4
5
function &func() {
    return $a;
}
$a = func();  //这种调用方式得到的不是引用传值
$a =& func(); //这样调用才是引用传值

请看下面详细的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$a = 1;
function &func(&$a) {
  return $a;
}
$b = func($a);
$c =& func($a);
$b = 2;
echo "a: $a, b: $b, c: $c. <br />/n";
//输出a: 1, b: 2, c: 1.
//可见对$b的修改不会影响$a
$c = 3;
echo "a: $a, b: $b, c: $c. <br />/n";
//输出a: 3, b: 2, c: 3.
//可见对$c的修改会影响$a

  

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

一、基本数据类型的传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* **************************************************** */ 
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<count ($arr);$i++){
4 for($j=$i+1;$j<count($arr);$j++){
5 if($arr[$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</count><count ($arr);$i++){
20 for($j=$i+1;$j<count($arr);$j++){
21 if($arr[$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 )

三、对象数据类型传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 的引用允许你用两个变量来指向同一个内容

1
2
3
4
5
6
7
$a="ABC";
$b =&$a;
echo $a;//这里输出:ABC
echo $b;//这里输出:ABC
$b="EFG";
echo $a;//这里$a的值变为EFG 所以输出EFG
echo $b;//这里输出EFG

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

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

  

6. ref:

  http://blog.sina.com.cn/s/blog_664c9f650101fl4b.html

  http://www.2cto.com/kf/201110/108970.html

  http://www.phpfensi.com/php/20140220/1612.html

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来开启.

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

1
2
3
4
5
function &func() {
    return $a;
}
$a = func();  //这种调用方式得到的不是引用传值
$a =& func(); //这样调用才是引用传值

请看下面详细的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$a = 1;
function &func(&$a) {
  return $a;
}
$b = func($a);
$c =& func($a);
$b = 2;
echo "a: $a, b: $b, c: $c. <br />/n";
//输出a: 1, b: 2, c: 1.
//可见对$b的修改不会影响$a
$c = 3;
echo "a: $a, b: $b, c: $c. <br />/n";
//输出a: 3, b: 2, c: 3.
//可见对$c的修改会影响$a

  

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

一、基本数据类型的传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* **************************************************** */ 
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<count ($arr);$i++){
4 for($j=$i+1;$j<count($arr);$j++){
5 if($arr[$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</count><count ($arr);$i++){
20 for($j=$i+1;$j<count($arr);$j++){
21 if($arr[$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 )

三、对象数据类型传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 的引用允许你用两个变量来指向同一个内容

1
2
3
4
5
6
7
$a="ABC";
$b =&$a;
echo $a;//这里输出:ABC
echo $b;//这里输出:ABC
$b="EFG";
echo $a;//这里$a的值变为EFG 所以输出EFG
echo $b;//这里输出EFG

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

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

  

6. ref:

  http://blog.sina.com.cn/s/blog_664c9f650101fl4b.html

  http://www.2cto.com/kf/201110/108970.html

  http://www.phpfensi.com/php/20140220/1612.htm

php函数值传值/地址以及引用的用法的更多相关文章

  1. Java中的值传递和地址传递(传值、传引用)

    首先,不要纠结于 Pass By Value 和 Pass By Reference 的字面上的意义,否则很容易陷入所谓的“一切传引用其实本质上是传值”这种并不能解决问题无意义论战中.更何况,要想知道 ...

  2. C#-Xamarin的Activity传值与Fragment引用

    前言 我们学习任何一个新框架时,肯定都需要学习它的子页面用法,因为子页面是封装公共内容最好的容器. 在Xamarin里子页面为Fragment,翻译过来是片段的意思. Fragment 下面我们来学习 ...

  3. JS 中没有按地址(引用)传递,只有按值传递

    很多人,包括我,受书本知识消化不彻底的影响,认为 JS 中参数有两种传递方式:数字.字符串等按值传递:数组.对象等按地址(引用)传递.对此种观点,我们要谨慎. var v1 = [] var v2 = ...

  4. java中的传值与传引用

    java函数中的传值和传引用问题一直是个比较“邪门”的问题,其实java函数中的参数都是传递值的,所不同的是对于基本数据类型传递的是参数的一份拷贝,对于类类型传递的是该类参数的引用的拷贝,当在函数体中 ...

  5. python函数传参是传值还是传引用?

    首先还是应该科普下函数参数传递机制,传值和传引用是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传 ...

  6. JavaScript系列----数据类型以及传值和传引用

    1.简单数据类型 在JavaScript中简单数据类型分为5种.分别为 Undefined, Null,Boolean,Number,String. Undefined类型Undefined类型只有一 ...

  7. Go 参数传递是传值还是传引用

    什么是传值(值传递)? 传值的意思是:函数传递的总是原来这个东西的一个副本.一个副拷贝.比如我们传递一个 int 类型的参数,传递 的其实这个参数的一个副本:传递一个指针类型的参数,其实传递的是这个指 ...

  8. Java内存管理-Stackoverflow问答-Java是传值还是传引用?(十一)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 本文导图: 一.由一个提问引发的思考 在Stack Overflow 看到这样一个问题 ...

  9. C++传值、传引用

    C++传值.传引用 C++的函数参数传递方式,可以是传值方式,也可以是传引用方式.传值的本质是:形参是实参的一份复制.传引用的本质是:形参和实参是同一个东西. 传值和传引用,对大多数常见类型都是适用的 ...

随机推荐

  1. Laravel小项目之第4节 Laravel-通过表单实现新增及操作状态提示功能

    第4节 Laravel-通过表单实现新增及操作状态提示功能 4.1 显示新增表单视图 4.2 通过模型实现新增 4.3 操作状态提示 4.1 显示新增表单视图 修改边栏的链接 \resources\v ...

  2. win7(64位)Sql server 用T-sql读取本地数据文件dbf的数据文件

    原文地址:https://www.cnblogs.com/cl1006/p/9924066.html 第一步启用Ad Hoc Distributed Queries  在SQLserver执行以下的语 ...

  3. CGLIB 和 JDK生成动态代理类的区别(转)

    文章转自http://luyuanliang.iteye.com/blog/1137292 AOP 使用的设计模式就是代理模式,是对IOC设计的补充.为了扩展性,往往会加上反射,动态生成字节码,生成代 ...

  4. StringRedisTemplate操作redis数据

    StringRedisTemplate与RedisTemplate区别点 两者的关系是StringRedisTemplate继承RedisTemplate. 两者的数据是不共通的:也就是说String ...

  5. Java不定参数Object… obj 和 Object[] 的区别

    Java不定参数Object… obj 和 Object[] 的区别 简述: java中方法重载可以实现参数不同自动匹配对应方法.但现实中也存在这种问题.普通传参对于形如下面的方法,却显得臃肿而失优雅 ...

  6. Vue组件基础

    <!DOCTYPE html><html>    <head>        <meta charset="utf-8">      ...

  7. 【Atcoder yahoo-procon2019-qual D】 Ears

    Atcoder yahoo-procon2019-qual D 题意:给你\(L\)个耳朵(???),以及一条范围从\(0\)到\(L\)的数轴,你可以选择一个出发点,从该点开始随意走动,如果经过了\ ...

  8. ubuntu 14.04 安装jdk 1.8

    一,如何删除低版本的open JDK? 在ubuntn的软件中心中,如果输入"Java",我们会看到open JDK,但是最高版本是1.7,也有1.6版本的,如果我们安装上去,可能 ...

  9. 17-(基础入门篇)GPRS(Air202)串口

    https://www.cnblogs.com/yangfengwu/p/9968716.html 现在看一下官方给的demo 其实只要有两个就好说了 module(...,package.seeal ...

  10. Topographic ICA as a Model of Natural Image Statistics(作为自然图像统计模型的拓扑独立成分分析)

    其实topographic independent component analysis 早在1999年由ICA的发明人等人就提出了,所以不算是个新技术,ICA是在1982年首先在一个神经生理学的背景 ...