新浪PHP开发工程师笔/面试总结三·静态变量和其他变量范围问题

接上回说到,变量范围里还有一个static关键字,即静态变量。PHP手册里对静态变量的说明是:

静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失。

静态变量也提供了一种处理递归函数的方法。递归函数是一种调用自己的函数。写递归函数时要小心,因为可能会无穷递归下去。必须确保有充分的方法来中止递归。


1
2
3
4
5
6
7
8
function test(){
static $count = 0;
echo $count ."\n";
$count++;
}
test();//输出0
test();//输出1
test();//输出2

还有递归调用时:

1
2
3
4
5
6
7
8
function test(){
static $count = 0;
echo $count ."\n";
$count++;
while($count<10)
test();
}
test();

则输出0到9。

此外,static关键字不能用表达式赋值,比如

1
static $a = 1+2;

是不可以的。

此外,static还有一个容易混淆的部分,就是声明类的时候如果使用了static变量,那么这个变量会对这个类的所有对象共享(changing value of a static in one instance changes value in all instances)。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class static_class{
public function func_static(){
static $count = 0;
$count++;
echo $count;
}
}

$a = new static_class();
$b = new static_class();

$a->func_static();//输出1
$b->func_static();//输出2
$a->func_static();//输出3

调试上述程序的时候还出现了个有趣的现象,感觉变量作用域的问题还是需要非常小心的。比如说如果希望每个类都有单独的变量的话,如果不慎把声明和使用写成如下形式:

1
2
3
4
5
private $count = 0;
public function func_static(){
$count++;
echo $count;
}

那么上述测试代码就会输出三个1。一开始的时候还怀疑过是不是用private声明有问题,后来才发现类里面的函数如果要调用类里面的对象,需要加入$this->才行。因为把前面的声明改成$count = 2还是会输出三个1。看来测试的时候要慎重选取初始值呀,等于0这样的表达式虽然写得很顺手,但是有可能会掩盖掉真正出错的原因。在上述例子里面出错的原因就是func_static函数里没有出现过$count变量,所以PHP就新建了一个局部的$count=0,所以才会输出三个1啦。

写成这样就可以了:

1
2
3
4
5
private $count = 0;
public function func_static(){
$this->count++;
echo $this->count;
}

本着现学现用的思想,在func_static里面声明引用也可以很好的解决上述问题,而且不用打这么多个$this,即

1
$count =& $this->count;

总结:

  • static关键字声明的变量在程序运行时值会一直保持,不会因为多次调用时被重复声明覆盖。
  • static关键字声明的变量在同一个类的不同实例里值会共享。