浅谈PHP变量作用域以及地址引用问题

作用域的概念:

在PHP脚本的任何位置都可以声明变量,但是,声明变量的位置会大大影响访问变量的范围。这个可以访问的范围称为作用域。

主要的常用的包括:局部变量、全局变量、静态变量。

1、局部变量:就是在函数内声明的变量,他保存在内存的栈内,所以访问速度很快。仅在函数内有效。

2、全局变量:与局部变量相反,全局变量可以在程序的任何地方访问。只要在变量前面加关键字GLOBAL,就可以将其识别为全局变量。在整个php文件内有效。

3、静态变量:用static修饰只存在于函数作用域的变量,函数执行结束后其值并不消失。注:初始化后不能再次进行初始化,不能用表达式来赋值。

代码如下:

function test()
{
static $b=0;//申明静态变量,放在函数外部声明的话,在函数内部是用不到的

$b=$b+1;

echo $b;
}
test();//这条语句会输出 $b的值 为1
test();//这条语句会输出 $b的值 为2

注:static $b=0 这一赋值操作只会在变量第一次被初始化的时候执行。

附A:类中静态成员和静态方法,差不多只是调用的时候统一使用类名或者self或者parent加::xxx,他们的作用域和这个一样,但是他的声明是在方法外部的

附B:js里面的作用域使:用var aa=‘xxx';在函数外面声明的就是全局变量(不管是否带有修饰符var)。在函数内部使用 var声明的是局部变量,不使用var修饰的是全局变量。

附C:关于引用

PHP引用:就是在变量、函数或者对象前加&.php中的引用就是想用不同的名字访问同一个变量的内容。

1、变量的引用:

代码如下:

$a="ABC";

$b =&$a;

echo $a;//这里输出:ABC

echo $b;//这里输出:ABC

$b="EFG";

echo $a;//这里$a的值变为EFG 所以输出EFG

echo $b;//这里输出EFG

2、函数的传址调用

代码如下:

function test(&$a)

{

$a=$a+100;

}

$b=1;

echo $b;//输出1

test($b); //这里$b传递给函数的其实是$b的变量内容所处的内存地址,通过在函数里改变$a的值 就可以改变$b的值了

echo "<br>";

echo $b;//输出101

3、函数的引用返回

代码如下:

function &test()
{

static $b=0;//申明一个静态变量

$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()得到的其实不是函数的引用返回。只是将函数的返回值复制给$a,而不会影响到$b。这样调用和普通的调用没区别。

Php规定:$a=&test()方式得到才是函数的引用返回。他将$b变量的内存地址和$a变量的内存地址指向了同一个地方。即相当于$a=&$b;

4、取消引用

代码如下:

$a = 1;

$b =& $a;

unset ($a);

echo $b;

解析:unset一个引用,只是取消了变量名和变量的内容之间的绑定,并不意味着内容被销毁,其值还是真实存在的。

5、global引用:使用global $var  声明一个变量时,其实就是建立了一个到全局变量的引用。Global $val <=> $var=&$GLOBALS[‘var'] ;

6、对象的引用:在对象的方法中,$this调用的对象都是调用它的引用

注:php中对于地址的指向不是由用户自己来实现的,而是通过zend核心实现的,php的引用采用的是“写拷贝”的原理,就是除非发生写操作,指向同一个地址的变量或对象是不会被拷贝的。

代码如下:

$a = 1;

$b =$a;

$a和$b都是指向同一个内存地址,并不是$a和$b占用不同的内存。

若是现在执行一句$a=”dsd”:$a和$b所指向的内存数据需要重新写一次,此时zend核心会自动判断。自动为$b产生一个$a的数据拷贝,重新申请一块内存进行存储。

(0)

相关推荐

  • PHP对象递归引用造成内存泄漏分析

    通常来说,如果PHP对象存在递归引用,就会出现内存泄漏.这个Bug在PHP里已经存在很久很久了,先让我们来重现这个Bug,示例代码如下: <?php class Foo { function __construct() { $this->bar = new Bar($this); } } class Bar { function __construct($foo) { $this->foo = $foo; } } for ($i = 0; $i < 100; $i++) { $ob

  • PHP变量的定义、可变变量、变量引用、销毁方法

    复制代码 代码如下: <?php$long="big_long_variable_name";$$long="PHP";     /* 用存放在变量$long里的字符串作为新变量的变量名,等同于$big_long_variable_name="PHP"; */$short=& $big_long_variable_name;  /* 取变量$big_long_variable_name的值赋给变量$short,此时$short的值为

  • php中引用符号(&)的使用详细介绍

    与C语言中的指针是有差别的.C语言中的指针里面存储的是变量的内容在内存中存放的地址变量的引用. PHP 的引用允许你用两个变量来指向同一个内容 $a="ABC"; $b =&$a; echo $a;//这里输出:ABC echo $b;//这里输出:ABC $b="EFG"; echo $a;//这里$a的值变为EFG 所以输出EFG echo $b;//这里输出EFG 函数的传址调用 传址调用我就不多说了 下面直接给出代码 <?php functio

  • php面向对象全攻略 (三)特殊的引用“$this”的使用

    7.特殊的引用"$this"的使用 现在我们知道了如何访问对象中的成员,是通过"对象->成员"的方式访问的,这是在对 象的外部去访问对象中成员的形式,那么如果我想在对象的内部,让对象里的方法访问本对 象的属性,或是对象中的方法去调用本对象的其它方法这时我们怎么办?因为对象里面的所 有的成员都要用对象来调用,包括对象的内部成员之间的调用,所以在PHP 里面给我提供了 一个本对象的引用$this,每个对象里面都有一个对象的引用$this 来代表这个对象,完成对象

  • PHP中函数内引用全局变量的方法

    先看下面的代码: 复制代码 代码如下: <?php $var1 = "#####"; $var2 = "&&&&&"; function global_references($use_globals) { global $var1, $var2; if (!$use_globals) { $var2 =&$var1; //1 } else { $GLOBALS["var2"] =&$v

  • php引用地址改变变量值的问题

    复制代码 代码如下: <?php $foo = 'Bob'; // 将 'Bob' 赋给 $foo $bar = &$foo; // 通过 $bar 引用 $foo echo $foo.'<br/>'; $bar = "My name is $bar"; // 修改 $bar 变量 echo $bar.'<br/>'; echo $foo.'<br/>'; // $foo 的值也被修改 ?> 输出: Bob My name is

  • php中引用&的用法分析【变量引用,函数引用,对象引用】

    本文实例分析了php中引用&的用法.分享给大家供大家参考,具体如下: php的引用(就是在变量或者函数.对象等前面加上&符号) //最重要就是 删除引用的变量 ,只是引用的变量访问不了,但是内容并没有销毁 在PHP 中引用的意思是:不同的名字访问同一个变量内容. 变量的引用 PHP 的引用允许你用两个变量来指向同一个内容 <?php $a="ABC"; $b =&$a; echo $a;//这里输出:ABC echo $b;//这里输出:ABC $b=&q

  • PHP对象相互引用的内存溢出实例分析

    通常来说使用脚本语言最大的好处之一就是可利用其拥有的自动垃圾回收机制来释放内存.你不需要在使用完变量后做任何释放内存的处理,因为这些PHP会帮你完成. 当然,我们可以按自己的意愿调用 unset() 函数来释放内存,但通常不需要这么做. 不过在PHP里,至少有一种情况内存不会得到自动释放,即便是手动调用 unset().详情可考PHP官网关于内存泄露的分析:http://bugs.php.net/bug.php?id=33595. 问题症状如下: 如果两个对象之间存在着相互引用的关系,如"父对象

  • php函数间的参数传递(值传递/引用传递)

    php:函数间的参数传递 1.值传递 复制代码 代码如下: <?php function exam($var1){ $var1++: echo "In Exam:" . $var1 . "<br />"; } $var1 = 1; echo $var1 . "<br />"; exam($var1); echo $var1 . "<br />"; ?> -------------

  • 浅谈PHP变量作用域以及地址引用问题

    作用域的概念: 在PHP脚本的任何位置都可以声明变量,但是,声明变量的位置会大大影响访问变量的范围.这个可以访问的范围称为作用域. 主要的常用的包括:局部变量.全局变量.静态变量. 1.局部变量:就是在函数内声明的变量,他保存在内存的栈内,所以访问速度很快.仅在函数内有效. 2.全局变量:与局部变量相反,全局变量可以在程序的任何地方访问.只要在变量前面加关键字GLOBAL,就可以将其识别为全局变量.在整个php文件内有效. 3.静态变量:用static修饰只存在于函数作用域的变量,函数执行结束后

  • 浅谈Javascript变量作用域问题

    Js中的变量作用域问题: 1.没有块级作用域.Js中的变量作用域不是以{}为界的,不像C/C++/Java. 如: 复制代码 代码如下: if(true){      var name = "qqyumidi";  }               alert(name);  // 结果:qqyumidi Js会将在if中定义的变量添加到当前的执行环境中,尤其在使用for循环时需要注意与其他语言的差异. 复制代码 代码如下: for(var i=0; i<10; i++){    

  • 浅谈C++变量作用域

    C++ 变量作用域 作用域是程序的一个区域,一般来说有三个地方可以定义变量: 在函数或一个代码块内部声明的变量,称为局部变量. 在函数参数的定义中声明的变量,称为形式参数. 在所有函数外部声明的变量,称为全局变量. 我们将在后续的章节中学习什么是函数和参数.本章我们先来讲解什么是局部变量和全局变量. 局部变量 在函数或一个代码块内部声明的变量,称为局部变量.它们只能被函数内部或者代码块内部的语句使用.下面的实例使用了局部变量: #include <iostream> using namespa

  • 浅谈PHP中关于foreach使用引用变量的坑

    写PHP好多年,但仍然会犯低级错误,今天遇到个 foreach中引用变量时的坑,PHP版本为 5.6.12 代码如下: <?php $arr = ['a', 'b', 'c', 'd', 'e']; foreach ($arr as $i=>&$a) { $a = $a.'_'. $a; echo $a .'<br>'; } echo '<hr>'; foreach ($arr as $i=>$a) { echo $a .'<br>'; } e

  • 浅谈Java中的四种引用方式的区别

    强引用.软引用.弱引用.虚引用的概念 强引用(StrongReference) 强引用就是指在程序代码之中普遍存在的,比如下面这段代码中的object和str都是强引用: Object object = new Object(); String str = "hello"; 只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象. 比如下面这段代码: public class Main { publi

  • 浅谈静态变量、成员变量、局部变量三者的区别

    静态变量和成员变量的区别: A:所属不同 静态变量:属于类,类变量    成员变量:属于对象,对象变量,实例变量 B:内存位置不同 静态变量:方法区的静态区    成员变量:堆内存 C:生命周期不同 静态变量:静态变量是随着类的加载而加载,随着类的消失而消失    成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失 D:调用不同 静态变量:可以通过对象名调用,也可以通过类名调用    成员变量:只能通过对象名调用 成员变量和局部变量的区别: A:在类中的位置不同 成员变量:在类中方法

  • 浅谈JavaScript变量的自动转换和语句

    JS自动类型转换 var a = 1; var b = true; "==" 表示 可以自动类型转换,比较的是数值  "===" 表示可以自动类型转换,先比较数值,再比较类型 if (a == b) { alert("相等"); //打印 }else{ alert("不等"); } 三目运算 var c = 10/2 > 4 ? 5 : 3 ; alert(c); 关于for循环 for ( var i = 0; i &

  • 浅谈springBean的作用域

    目录 bean的作用域具体实现 代码分析 前言:最近在进行springBean的作用域学习,并且学习了对应的例子.这里进行一下总结 一:Bean的作用域基础概念 如果想学习SpringBean的生命周期,那么就必须要学习Bean的作用域.因为不同的作用域的bean的生命周期不同 1:singleton(唯一bean实例,由Spring容器管理其生命周期)2:prototype(原型bean,创建后容器不管理其生命周期)3:request(每次http都产生新的bean,仅在http reques

  • 浅谈Python浅拷贝、深拷贝及引用机制

    这礼拜碰到一些问题,然后意识到基础知识一段时间没巩固的话,还是有遗忘的部分,还是需要温习,这里做份笔记,记录一下 前续 先简单描述下碰到的题目,要求是写出2个print的结果 可以看到,a指向了一个列表list对象,在Python中,这样的赋值语句,其实内部含义是指a指向这个list所在内存地址,可以看作类似指针的概念. 而b,注意,他是把a对象包裹进一个list,并且乘以5,所以b的样子应该是一个大list,里面元素都是a 而当a对象进行了append操作后,其实,隐含的意思是,内存中的这个l

  • 浅谈const变量赋值报错分析

    从变量到常量的赋值是合法C++的语法约定的, 如从char 到const char顺畅: 但从char **到 const char **编译器就会报错: 复制代码 代码如下: error: invalid conversion from `char**' to `const char**' 示例: int main(int argc, char *argv[]) { char a = '1'; const char b = a; char * a2 = "12345"; const

随机推荐