PHP之static静态变量详解

什么是static静态变量?(以下为在C语言中的理解)

静态变量 类型说明符是static。

静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在静态存储区内分配存储单元),该 区域中的数据在整个程序的运行期间一直占用这些存储空间(在程序整个运行期间都不释放),也可以认为是其内存地址不变,直到整个程序运行结束(相反,而 auto自动变量,即动态局部变量,属于动态存储类别,占动态存储空间,函数调用结束后即释放)。静态变量虽在程序的整个执行过程中始终存在,但是在它作 用域之外不能使用。

另外,属于静态存储方式的变量不一定就是静态变量。 例如:外部变量(在PHP中指全局变量)虽属于静态存储方式,但不一定是静态变量,必须由 static加以定义后才能成为静态外部变量,或称静态全局变量。

所有的全局变量都是静态变量,而局部变量只有定义时加上类型修饰符static,才为局部静态变量。

静态变量可以在任何可以申请的地方申请,一旦申请成功后,它将不再接受其他的同样申请。

静态变量并不是说其就不能改变值,不能改变值的量叫常量。 其拥有的值是可变的 ,而且它会保持最新的值。说其静态,是因为它不会随着函数的调用和退出而发生变化。即上次调用函数的时候,如果我们给静态变量赋予某个值的话,下次函数调用时,这个值保持不变。

一、静态局部变量:

1、static类型的内部变量同auto自动变量(即未加 static 声明的局部变量)一样,是某个特定函数的局部变量,即只能在定义该变量的函数内使用该变量,两者作用域相同;两者的不同在于:auto自动变量会随着函数被调用和退出而存在和消失,而static类局部变量不会,它不管其所在的函数是否被调用,都将一直存在;不过,尽管该变量还继续存在,但不能使用它。倘若再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。换言之,static类型的内部变量是一种只能在某个特定函数中使用,但一直占据存储空间的变量。

2、函数体内如果在定义静态变量的同时进行了初始化,则以后程序不再进行初始化操作(出现在函数内部的基本类型的的静态变量初始化语句只有在第一次调用才执行)。而对自动变量赋初值是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。

3、静态局部变量的初始化表达式必须是一个常量或者常量表达式。即使局部静态变量定义时没有赋初值,系统会自动赋初值0(对数值型变量)或空字符(对字符变量);静态变量的初始值为0。而对自动变量auto来说,如果不赋初值则它的值将是个不确定的值。

4、当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成意外的副作用(主要是变量的作用域造问题成的),因此仍以采用局部静态变量为宜。

注:局部静态变量占用内存时间较长,并且可读性差,因此,除非必要,尽量避免使用局部静态变量。

二、静态全局变量

全局变量(外部变量)的声明之前再冠以static 就构成了静态的全局变量。

全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式

这两者在存储方式上并无不同。

这两者的区别虽在于:

1、非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。

2、静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。

从以上分析可以看出————

把局部变量改变为静态变量后是改变了它的存储方式,即改变了它的生存期。
把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。static静态变量会被放在程序的全局存储区中(即在程序的全局数据区,而不是在堆栈中分配,所以不会导致堆栈溢出),这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。

三、应用于PHP中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
//--------------如何理解static静态变量-----------
 
/** 普通局部变量 */
function local() {
     $loc = 0; //这样,如果直接不给初值0是错误的。
     ++ $loc ;
     echo $loc . '<br>' ;
}
local(); //1
local(); //1
local(); //1
echo '===================================<br/>' ;
 
/** static静态局部变量 */
function static_local() {
     static $local = 0 ; //此处可以不赋0值
     $local ++;
     echo $local . '<br>' ;
}
static_local(); //1
static_local(); //2
static_local(); //3
//echo $local; 注意虽然静态变量,但是它仍然是局部的,在外不能直接访问的。
echo '=======================================<br>' ;
 
/** static静态全局变量(实际上:全局变量本身就是静态存储方式,所有的全局变量都是静态变量) */
function static_global() {
     global $glo ; //此处,可以不赋值0,当然赋值0,后每次调用时其值都为0,每次调用函数得到的值都会是1,但是不能想当然的写上"static"加以修饰,那样是错误的.
     $glo ++;
     echo $glo . '<br>' ;
}
static_global(); //1
static_global(); //2
static_global(); //3
?>

static用法如下:

1.static 放在函数内部修饰变量

2.static放在类里修饰属性,或方法

3.static放在类的方法里修饰变量

4.static修饰在全局作用域的变量

所表示的不同含义如下:

1.在函数执行完后,变量值仍然保存

如下所示:

1
2
3
4
5
6
7
8
9
10
<?php
function testStatic() {
     static $val = 1;
     echo $val ;
     $val ++;
}
testStatic();   //output 1
testStatic();   //output 2
testStatic();   //output 3
?>

2.修饰属性或方法,可以通过类名访问,如果是修饰的是类的属性,保留值

如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class Person {
     static $id = 0;
 
     function __construct() {
         self:: $id ++;
     }
 
     static function getId() {
         return self:: $id ;
     }
}
echo Person:: $id ;   //output 0
echo "<br/>" ;
 
$p1 = new Person();
$p2 = new Person();
$p3 = new Person();
 
echo Person:: $id ;   //output 3
?>

3.修饰类的方法里面的变量

如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class Person {
     static function tellAge() {
         static $age = 0;
         $age ++;
         echo "The age is: $age
";
     }
}
echo Person::tellAge(); //output 'The age is: 1'
echo Person::tellAge(); //output 'The age is: 2'
echo Person::tellAge(); //output 'The age is: 3'
echo Person::tellAge(); //output 'The age is: 4'
?>

4.修饰全局作用域的变量,没有实际意义(存在着作用域的问题,详情查看

如下所示:

1
2
3
4
5
<?php
static $name = 1;
$name ++;
echo $name ;
?>

另外:考虑到PHP变量作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
include 'ChromePhp.php' ;
 
$age =0;
$age ++;
 
function test1() {
     static $age = 100;
     $age ++;
     ChromePhp::log( $age );  //output 101
}
 
function test2() {
     static $age = 1000;
     $age ++;
     ChromePhp::log( $age ); //output 1001
}
 
test1();
test2();
ChromePhp::log( $age ); //outpuut 1
?>

可以看出:这3个变量是不相互影响的,另外,PHP里面只有全局作用域和函数作用域,没有块作用域

如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
include 'ChromePhp.php' ;
 
$age = 0;
$age ++;
 
for ( $i =0; $i <10; $i ++) {
     $age ++;
}
ChromePhp::log( $i );   //output 10;
ChromePhp::log( $age ); //output 11;
?>

参考资料:

https://www.cnblogs.com/52php/p/5658171.html

https://www.cnblogs.com/52php/p/5658168.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值