本节内容:
PHP变量内存分配问题
一个关于php变量内存分配的问题,例如代码:
$a = array (
'str' => 1,
'child' => 2
);
$b = $a;
$b['child'] = $a;
$b['child']['str'] = 2;
echo $b['str'];
$b = null;
echo $a['str'];
输出结果:
11,$b=$a时其实并没有新分配内存,ab是指向的同一个区域,$b['child']=$a时,$b会先copy一份原来$a的内容,然后再修改。
此时$b和$a指向了不同的区域,再修改$a或者$b的时候都不会互相影响了。
再看这段代码:
{ // www.
public $str = '';
public $child;
}
$a = new A();
$b = $a;
$a->str = 1;
$a->child = 2;
$b->child = $a;
$b->child->str = 2;
echo $b->str;
$b = null;
echo $a->str;
输出结果:22,根据实际情况来判断,$b->child=$a时,并没有像数组那样,重新copy一份,ab以及a->child都是指向的同一片区域,这样改任何一个,其余几个都会被改掉。
不理解,PHP为什么设计成如此呢?
本节内容:
php取整函数ceil、floor、round、intval
在php编程中,遇到数据处理取整时,有以上四个函数可供选择。
1、ceil — 进一法取整
说明
float ceil ( float $value )
返回不小于 value 的下一个整数,value 如果有小数部分则进一位。ceil() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。
ceil() 例子
echo ceil(4.3); // 5
echo ceil(9.999); // 10
?>
2、floor — 舍去法取整
说明
float floor ( float $value )
返回不大于 value 的下一个整数,将 value 的小数部分舍去取整。floor() 返回的类型仍然是 float,因为 float 值的范围通常比 integer 要大。
floor() 例子
echo floor(4.3); // 4
echo floor(9.999); // 9
?>
3、round — 对浮点数进行四舍五入
说明
float round ( float $val [, int $precision ] )
返回将 val 根据指定精度 precision(十进制小数点后数字的数目)进行四舍五入的结果。precision 也可以是负数或零(默认值)。
round() 例子
echo round(3.4); // 3
echo round(3.5); // 4
echo round(3.6); // 4
echo round(3.6, 0); // 4
echo round(1.95583, 2); // 1.96
echo round(1241757, -3); // 1242000
echo round(5.045, 2); // 5.05
echo round(5.055, 2); // 5.06
?>
说明: PHP 默认不能正确处理类似 “12,300.2″ 的字符串。
说明: precision 参数是在 PHP 4 中被引入的。
4、intval — 获取变量的整数值
说明
int intval ( mixed $var [, int $base ] )
通过使用特定的进制转换(默认是十进制),返回变量 var 的 integer 数值。
var 可以是任何标量类型。intval() 不能用于 array 或 object。
intval() 例子
echo intval(4.3); // 4
echo intval(9.999); // 9
?>
说明:
除非 var 参数是字符串,否则 intval() 的 base 参数不会有效果。
小结:
floor函数与intval函数功能相同,所不同之处是一个返回的浮点数(float),而另一个是整数(integer),因为 float 值的范围通常比 integer 要大。不过就数值本身来说
两者是相等的。
本节内容:
php垃圾回收机制
我们知道,PHP语言是没有内存驻留机制的,当脚本执行完成之后所有的资源全部释放。
因此,在php编程中,所有的PHP的变量都存储在一个叫做zval的容器里,zval里不光存着变量的类型与值,还存储了另外两个信息,一个是is_ref,用来标识该变量是否是一个引用,另外一个是refcount,用来存储有几个变量指向两个该zval。
介绍一个函数:xdebug_debug_zval 这个函数是xdebug扩展提供的,安装xdebug扩展之后就可以在代码里调用了,安装方法和下载地址:http://xdebug.org/。
这个函数就可以看到php变量的内部结构。
例子:
$a = "new string";
xdebug_debug_zval( 'a' );
?>
输出:
a: (refcount=1, is_ref=0)='new string'
refcount=1代表有一个变量指向该zval,就是$a。
$a = "new string";
$b = $a;
xdebug_debug_zval( 'a' );
?>
输出:
a: (refcount=2, is_ref=0)='new string'
问题分析:当变量互相赋值时,php引擎并没有创建一个新的zval,只是把这些变量都指向了相同的zval。
$a = "new string";
$c = $b = $a;
xdebug_debug_zval( 'a' );
unset( $b, $c );
xdebug_debug_zval( 'a' );
?>
输出:
a: (refcount=3, is_ref=0)='new string'
a: (refcount=1, is_ref=0)='new string'
当调用unset,=null,或者赋给别的非空值,则refcount就会自减。
如果再调用unset($a),则该zval的refcount就减为0了,这个空间也就会被释放。
以上都是所谓的scalar types,标量类型的变量。
补充一些基础知识:
PHP中的数据类型:
PHP支持8种基本的数据类型,包括:
四种标量类型(scalar types):
boolean
integer
float (同double )
string
两种复合类型(compound types);
array
object
两种特殊类型:
resource(比如mysql的链接,mysql结果集等都属这类)
NULL
接下来,说下php中垃圾回收的问题,以上说的都是所谓的变量类型的变量,这里说下array和object。
当使用array和object时,如果处理不当,上述的垃圾回收机制就会造成一定的问题,当出现下述情况:
$a = array( 'one' );
$a[] =& $a;
xdebug_debug_zval( 'a' );
?>
输出:
a: (refcount=2, is_ref=1)=array (
0 => (refcount=1, is_ref=0)='one',
1 => (refcount=2, is_ref=1)=...
)
此时a指向的zval的refcount是2,如果调用unset($a),这时该zval的refcount变成了1,而不是0,该zval不应该被释放,但是指向这个zval的外部链接已经没有了,即没有办法再访问到这个zval了,也就无法再减少refcount了,于是乎这个zval就挂在那了。只有当脚本执行完成之后,才会释放。
可能对于一般的应用,这种情况不会造成太大的问题,但是如果要写一个长时间运行的程序比如一个daemon程序的话,就得注意了。
不过PHP5.3更新了垃圾回收的算法,用以解决这个问题,把所有这种无头的zval都放到一个缓存区里,缓存慢了之后,就会挨个递归检查这些zval,有外连的保留,无外连得释放,算法的具体情况有时间再写。
有关php垃圾回收机制的问题,就介绍这些吧,希望有助于你的理解。
,祝大家学习进步。