PHP对象类型在内存中的分配,PHP对象类型在内存中的分配

本文详细介绍了PHP中对象类型数据在内存中的分配,包括栈空间和堆空间的使用。对象因其大小不确定和占用空间较大,被存储在堆内存中,而对象的引用存储在栈内存。通过实例展示了对象创建和引用的过程,并讨论了克隆对象时内存的变化。

对象类型和整型、字符串一样,也是PHP的一种数据类型。都是在程序中用于存储不同类型数据使用,在程序运行时它的每个部分内容都要现加载到内存中在被使用。那么对象类型的数据在内存中是如何分配的呢?

首先,我们了解下内存结构。逻辑上内存大体上被分为四段,分别为栈空间段、堆空间段、初始化数据段、代码段,程序中不同类型数据的声明将会被存放在不同的内存段里面。

1、栈空间段

栈的特点是空间小但被CPU访问的速度快,是用户存放程序中临时创建的变量。由于栈的后进先出特点,所以栈特别方便用来保存和恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个临时数据寄存、交换的内存区。用于存储占用空间长度不变且占用空间小的数据类型的内存段,例如整型(1、100、10000等在内存中占用空间是等长的,占用空间都是32位4个字节)、double、boolean等都可以存储在栈空间段中。

2、堆空间段

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可以动态扩张或缩减。用于存储数据长度可变或占用内存比较大的数据。例如字符串、数组、对象等就存储在堆空间段中。

3、初始化数据段

数据段用来存放可执行文件中已经初始化全局变量,换句话说就是存放程序静态分配的变量。

4、代码段

代码段是用来存放可执行文件的操作指令,也就是说它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作。例如,程序中的函数就存放在这段内存中。

如图:

b14d823ac9586c541f9976b84b1be44e.png

程序在运行时,栈内存中的数据是可以直接存取的,而堆内存是不可以直接存取的。对象类型的数据是一种占用空间比较大,而且是占用空间长度不定长的数据类型,所以对象创建完成以后被存放在堆内存中,但对象的引用名称是存放在栈里面的。运行程序时,可以通过对象的引用名称访问对象中的成员。

实例:

classPerson{var $name; //成员属性,人的姓名

var $age;//成员属性,人的年龄

var $sex;//成员属性,人的性别

function eat(){ //成员方法,吃饭方式

echo '人在吃饭';

}

}//通过person类,实例化三个对象$p1、$p2、$p3

$p1 = newPerson();$p2 = newPerson();$p3 = newPerson();?>

如图:

00853c9e98571dc97f743a13c4b7a81c.png

从上图可以看到,等号右边是创建的真正对象实例,被存储在堆内存中,而等号左边则是对象的引用,被存储在栈内存段中。

上图一共有三个new Person,所以会在堆内存中开辟出三个独立的空间,产生3个实例对象,每个实例对象都是独立的,独享自己的空间。

每个在堆里面的实例对象是存储属性的,比如说,现在堆里面的实例对象里面都存有姓名、性别和年龄。每个属性又都有一个地址。

$p1=new Person();

等号的左边$p1 是一个引用变量,通过赋值运算符“=”把对象的首地址 赋给“$p1”这个引用变量,所以$p1 是存储对象首地址的变量,$p1 放在栈内存里边,$p1 相当 于一个指针指向堆里面的对象,所以我们可以通过$p1 这个引用变量来操作对象,通常我们也称对象引用为对象。

话外篇:分析下面的代码,你会得出什么理论?

classPerson{public $name = 'test';

}$obj1 = newPerson();$obj1->name = "test1";echo $obj1->name; //输出:test1

echo '


';$obj2_0 = clone $obj1;$obj2_0->name = "test2_0";echo $obj1->name; //输出:test1

echo '


';echo $obj2_0->name; //输出:test2_0

echo '


';$obj2 = $obj1;$obj2->name = "test2";echo $obj1->name; //输出:test2

echo '


';echo $obj2->name; //输出:test2

echo '


';$obj3 = newPerson();echo $obj3->name; //输出:test

等号左边是对象的指针而不是对象本身, 所以obj2和obj1都指向同一块内存,同一个对象。这一点和OOP语言是一样

object(Person)[2]public'name' =>string'test2'(length=5)object(Person)[2]public'name'=>string'test2'(length=5)可见对象的ID号是一个

如果想得到一个对象的副本,用$obj2 =clone $obj1;  用了clone后会产生一个新对象,分配内存,独立于原来的obj1

$obj2 = $obj1;

$obj2 = &$obj1;

一样的效果,一样的解释?

对于object来说,是一样的。 对于普通的变量是不一样的。

$a = 1;

$b = $a;

$c = &$a;

不一样的,具体可以看传值和传引用的区别。

(此篇是根据自己的理解对网上的一篇文章做了一些改动,在此感谢原作者。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值