Awezome

  • 主页
  • 随笔
所有文章 友链 关于我

Awezome

  • 主页
  • 随笔

[转] PHP对象在内存中的分配说明

2014-03-21

最近小组分享了php内存方面的知识,前几篇也转载了别人的讲得很好的文章,下面是关于对象在内存的分配情况。
from : http://www.cnblogs.com/mo-beifeng/archive/2011/10/08/2201685.html

对象在PHP 里面和整型、浮点型一样,也是一种数据类,都是存储不同类型数据用的, 在运行的时候都要加载到内存中去用,那么对象在内存里面是怎么体现的呢?内存从逻辑上 说大体上是分为4 段,栈空间段、堆空间段、代码段、初始化静态段,程序里面不同的声明 放在不同的内存段里面,数据段(data segment)通常是指用来存放程序中已初始化且不为0的全局变量如:静态变量和常量;代码段(code segment / text segment)通常是指用来存放程序执行代码的一块内存区域,比如函数和方法;栈空间段是存储占用相同空间长度并且占用空间小的数据类型的地方,比如说整型1,10,100,1000,10000,100000 等等,在内存里面占用空间是等长的,都是64 位4 个字节。那么数据长度不定长,而且占有空间很大的数据类型的数据放在那内存 的那个段里面呢?这样的数据是放在堆内存里面的。如下图:

栈内存是可以直接存取的,而堆内存是 不可以直接存取的内存。对于我们的对象来数就是一种大的数据类型而且是占用空间不定长的类型,所以说对象是放在堆里面的,但对象名称是放在栈里面的,这样通过对象名称就可 以使用对象了。$p1 就是我们实例出来的对象名称,同理,$p2,$p3 也是我们实例出来的对象名称,一个类可以实例出多个对象,每个对象都是独立的,上面的代码相当于实例出来3 个人来,每个人之间是没有联系的,只能说明他们都是人类,每 个人都有自己的姓名,性别和年龄的属性,每个人都有说话和走路的方法,只要是类里面体 现出来的成员属性和成员方法,实例化出来的对象里面就包含了这些属性和方法。

1
$p1=new Person();

对于这个条代码,$p1 是对象名称在栈内存里面new Person()是真正的对象是在堆内存 里面的,具体的请看下图:

从上图可以看出$p1=new Person();等号右边是真正的对象实例,在堆内存里面的实体, 上图一共有3 次new Person(),所以会在堆里面开辟3 个空间,产生3 个实例对象,每个对象之间都是相互独立的,使用自己的空间,在PHP 里面,只要有一个new 这个关键字出现就会 实例化出来一个对象,在堆里面开辟一块自己的空间。 每个在堆里面的实例对象是存储属性的,比如说,现在堆里面的实例对象里面都存有姓 名、性别和年龄。每个属性又都有一个地址。 $p1=new Person();等号的右边$p1 是一个引用变量,通过赋值运算符“=”把对象的首地址 赋给“$p1”这个引用变量,所以$p1 是存储对象首地址的变量,$p1 放在栈内存里边,$p1 相当 于一个指针指向堆里面的对象,所以我们可以通过$p1 这个引用变量来操作对象,通常我们也 称对象引用为对象。

先看一个简单的类

1
2
3
4
5
6
7
8
class student{
public name;
public senggao;
private static check ;
public function name ($name){
$this ->name = $name;
}
}

首先对象的引用是保存在内存的栈区,$xiaoming = new student();

那么$xiaoming就是 new xiaoming();这个对象的引用

在 堆区里保存的是是这个对象

在初始化数据区存放的是静态属性(常量也保存在这里吗?)

在代码区存的是对象的方法

一个事实就是 变量的赋值,是传递变量的拷贝,而对象的赋值是传递对象本身

$a = 100; $b =$a; 这里传递一个$a 的拷贝给$b 在内存里,有两个100的数据块,一个给$a 一个给$b 相互不影响,所以改变$b时,$a不受影响

那么$a = new a(); $b = $a时,这里传递的是变量本身 意思是 在栈区有一个$a ,一个$b 他们的指向,都是堆区的同一个对象,所以$a 和$a是完全相同的,因为指向都是堆区的同一个对象

$xiaoming = new student(); $liming = new student();会发生什么

这时栈区有一个对象的引用$xiaoming 和$liming 在堆区会复制两份对象$xiaoming指向堆区$xiaoming的对象,而$liming 也指向堆区$liming的对象

然后在初始化数据区static check 却只有一份,是的只有一份,静态属性并不在堆区 静态方法服务于类 而不服务于对象,所以访问静态方法的时候,可以无需通过对象而直接访问 student::check 无需产生一个对象 顺便提下self::是访问当前类的静态方法或属性,是当前类,self在那个类里面,就是哪个类

在代码区的成员方法,同一个类只有一份,实例化多次,也只有一份,因为方法都是固定的,无需多次拷贝

64fa67dd005f5d405882dd0f

对象的内存分布:

  1. 对象的引用放在“栈内存”(栈放固定的内容)
  2. 对象是放在堆内存(堆内存放可变的内容)
  3. 静态成员放在“数据区”,在第一次加载时放入,可以让堆内存里的每个对象共享
  4. 函数和方法放在代码区
赏

谢谢你请我吃糖果

  • 内存
  • PHP

扫一扫,分享到微信

设计模式学习简单总结
博客优化设置记录
© 2014-2019 Awezome
Hexo Theme Zilia by Awezome