Object类型占用多大内存?

Object占多少内存,谁也不知道,按照非托管的想法是,如果你只定义一个类,而它没有任何数据成员,我在VS2008下,使用默认字节对齐, 
class Object 
{ 

}; 
这样得出来 sizeof( Object ) 为 1。 

在C#里,是不能直接获取object占用内存大小的,因为它根本不是一个标准的布局。 
而楼上的BinaryFormatter的方法,只是以二进制格式将对象或整个连接对象图形序列化和反序列化。它甚至还有可能包含版本信息,所以它的结果并不能代表一个对象所占用内存的大小。 
C#提供了一种可以获取一个对象的非托管内存的大小的方法。但是必须在显式指定了内存布局以及字节对齐等信息的对象上才可以使用。 

现在我们定义如下对象: 
[StructLayout( LayoutKind.Sequential )] 
public class MyObject 
{ 
} 
,大家都知道,所有的对象都是从MyObject继承而来的,也就是说,我们上面这个MyObject类,也隐含的继承了Object。 
那么,现在我们看看这段代码: 
int size = Marshal.SizeOf( typeof( MyObject ) ); 
运行结果是1。 
看来跟C++是一样的。也就是说,一个未定义任何数据成员的空对象,其占用1字节的内存。 

那么我们再来看看一些标准成员的大小,比如int,long,double等。 
int size = Marshal.SizeOf( typeof( int ) ); //结果为4 
int size = Marshal.SizeOf( typeof( long ) ); //结果为8 
int size = Marshal.SizeOf( typeof( float ) ); //结果为4 
int size = Marshal.SizeOf( typeof( double ) ); //结果为8 
可见,这些基本数据类型,与非托管下的大小是没有区别的。 

那么现在我们来看看混合在一起的情况。 
[StructLayout( LayoutKind.Sequential )] 
public class MyDataObject 
{ 
public byte a; 
public int x; 
public Char b; 
public double c; 
} 
然后我们执行 int size = Marshal.SizeOf( typeof( MyDataObject ) ); 
会发现结果是24。 
为什么是24呢,是因为我们指定了LayoutKind.Sequential,它的MSDN的说明如下: 
对象的成员按照它们在被导出到非托管内存时出现的顺序依次布局。这些成员根据在 System.Runtime.InteropServices.StructLayoutAttribute.Pack中指定的封装进行布局,并且可以是不连续的。 

那么,MyOjbect 的大小实际上就是所有数据成员内存字节对齐后然后结构体的大小。 
则VS2008上,字节对齐(即StructLayoutAttribute.Pack)默认设置好像是8。 
下面是MyDataObject对象在默认设置下的对齐情况: 
成员 偏移位置(字节) 内存分布(字节) 
a 0 0 
x 4 4-7 
b 8 8 
c 16 16-23 
总长度为24 
现在我们来看字节对齐为4的情况: 
成员 偏移位置(字节) 内存分布(字节) 
a 0 0 
x 4 4-7 
b 8 8 
c 16 12-19 
总长度为20。 
字节对齐为2的情况: 
成员 偏移位置(字节) 内存分布(字节) 
a 0 0 
x 4 2-5 
b 8 6 
c 16 8-16 
总长度为16。 
字节对齐为1的情况:这就是最紧凑的情况了。 
成员 偏移位置(字节) 内存分布(字节) 
a 0 0 
x 4 1-4 
b 8 5 
c 16 6-13 
总长度为14。 

总体上来说,.net的对象占用的空间,跟其它非托管程序是一样的,只是大部分的对象,由于是托管的,而且没有规定内存布局,所以我们无法获得其真正占用内存的大小。 

PS: 
StructLayoutAttribute类和Marshal类位于命名空间“System.Runtime.InteropServices”下。 

本来上面的对齐的排列顺序,我写的的时候中间有好几个空格的,不知道为什么发上来就成一个空格了,排版不好看了,效应着看吧,呵呵 

//------------我也来更新一下,不知道你们两个人在争什么? 
.net是中间语言,什么叫做托管?托管的主要意思就是它把内存控制权接管了,简之,你所写的代码并不是像C/C++那样对内存的精确控制。 

就拿C#来说,它是号称没有指针,但是,实际上大家都看得出来,它的所谓引用型参数,就是指针。为什么这么说?你试试调用一个非托管的API,如果那个参数是指针类型的话,那你就得用ref了。 

就拿你的问题ClassA a来说,现在我们就假定.net内部是指针,那么 
ClassA a,就相当于是定义了一个指针,我们知道,指针在32位系统下,占4字节。当然,这里还有一个前提,就是ClassA是一个class,不是struct或者其它值类型。 

至于string类型的成员的占用内存的大小,不知道楼主你会不会C++,有没有见过std的string是怎么实现的?为了提交效率,降低内存分配频率,string对象在创建时,就会默认了一个容量长度,这个跟它存储的字符串长度是不一样的,如果存储的字符串长度超过了容量,那么它会再重新分配一块更大的内存来存储。但目前我还没看到.net的String对象的源代码,所以不知道它的默认容量是多大,那个就应该是它默认占的内存大小。我只知道StringBuilder的默认容量是16,我想string的也许更大些吧。 

末了,不知道你们讨论一个托管对象的占用内存大小还有什么意义。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值