实例化一个类,在内存中分配多大的空间,?

hebeijg 2009-02-25 10:16:27
有两个类
class ClassA
{
int a;
}

class ClassB
{
int a;
int b;
}
class ClassB
{
int a;
int b;
public void Test()
{
string s ="test";
}
}

请问这三个类实例化的时候在内存里分配的内存大小有什么区别呢?

谢谢
...全文
433 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
king19840811 2009-02-25
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 Garnett_KG 的回复:]
32bit-下

classA: 12Byte -->4字节数据, 4字节内存同步块索引,4字节的类型对象指针
classB: 16Byte -->8字节数据, 4字节内存同步块索引,4字节的类型对象指针
classC: 16Byte -->8字节数据, 4字节内存同步块索引,4字节的类型对象指针
[/Quote]

good
aini1314lin 2009-02-25
  • 打赏
  • 举报
回复
学习
Garnett_KG 2009-02-25
  • 打赏
  • 举报
回复
32bit-下

classA: 12Byte -->4字节数据, 4字节内存同步块索引,4字节的类型对象指针
classB: 16Byte -->8字节数据, 4字节内存同步块索引,4字节的类型对象指针
classC: 16Byte -->8字节数据, 4字节内存同步块索引,4字节的类型对象指针
ctan 2009-02-25
  • 打赏
  • 举报
回复
在C#中讨论这个问题没有什么意义

大家可以学了C或C++, 把那里的概念拿来硬套C#, 试图计算class所占内存空间,
这有什么意义呢? class是引用类型, 它的空间不仅包含变量(C#中称为域)占用空间, 还包含函数(C#中称为方法)引用所占的空间,
估计随着C#版本的变化, 编译器处理时还会有所变化

C#中本来就避免对内存空间进行精确定位, 如取消指针就是例证之一
Dobzhansky 2009-02-25
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 iwxiaot 的回复:]
跟C++不一样呀,在程序里也得不到,学习
[/Quote]

它认为我们不需要知道这个大小

内存都 managed 了, 也爽, 也不爽
iwxiaot 2009-02-25
  • 打赏
  • 举报
回复
跟C++不一样呀,在程序里也得不到,学习
Dobzhansky 2009-02-25
  • 打赏
  • 举报
回复
// 但是第三个有了一个函数,为什么没有变呢?

函数是 type 的, 虚函数表机制

不是对象的
xuan.ye 2009-02-25
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 hebeijg 的回复:]
谢谢楼上两位的回复,能请两位解释下,为什么是取这些值吗?
谢谢
[/Quote]
因为本人能力有限也是凭感觉说的,所以lz还应该多方求证
class ClassA
{
int a;
}
8 ---对象+int a 对象 4b a 4b

class ClassB
{
int a;
int b;
}

12 同上 a -4b ,b-4b,对象 4b

class ClassB
{
int a;
int b;
public void Test()
{
string s ="test";
}
}
12 a-4b,b-4b,对象 4b ,函数没有空间
hebeijg 2009-02-25
  • 打赏
  • 举报
回复
按照楼上说的,int是4,那ClassA是一个引用类型,在堆栈里首先要建立一个4位的的指针,指向托管堆里分配内存,里面有一个int 所有又4字节
所以第一个是8,第二个是12,但是第三个有了一个函数,为什么没有变呢?
Dobzhansky 2009-02-25
  • 打赏
  • 举报
回复
参考文献:
.NET Framework Internals: How the CLR Creates Runtime Objects
http://msdn.microsoft.com/en-us/magazine/cc163791.aspx
ShinNakoruru 2009-02-25
  • 打赏
  • 举报
回复
厄,貌似有个地方我搞错了,若考虑内存对齐,也许答案应该是 8 8 16
Dobzhansky 2009-02-25
  • 打赏
  • 举报
回复
用个简单的例子, 装箱的 int

object i = new int(0);

这时, 发生了:
1. 托管堆上分配了 12 个字节(8字节的对象头 + 4 字节用于保存整数值)
2. 工作堆栈上一个局部变量 i 指向了托管堆中的那个装箱后的匿名对象.

8 字节对象头是所有位于托管堆上的对象都有的.

ShinNakoruru 2009-02-25
  • 打赏
  • 举报
回复
C#因为是托管代码,所以具体是多少字节我还真没去研究过
按照C++的想法,ClassA只有一个int,4字节,同理B 8字节,第二个B多了一个函数指针,12字节。

我想知道2楼的值是怎么得出的
hebeijg 2009-02-25
  • 打赏
  • 举报
回复
谢谢楼上两位的回复,能请两位解释下,为什么是取这些值吗?
谢谢
ShinNakoruru 2009-02-25
  • 打赏
  • 举报
回复
我有点晕
C#还真没考虑过

不过我怎么感觉
class ClassA
{
int a;
}
4 byte

class ClassB
{
int a;
int b;
}

8 byte

class ClassB
{
int a;
int b;
public void Test()
{
string s ="test";
}
}
12 byte
呢?去做一个试试看……
xuan.ye 2009-02-25
  • 打赏
  • 举报
回复
class ClassA
{
int a;
}
8

class ClassB
{
int a;
int b;
}

12

class ClassB
{
int a;
int b;
public void Test()
{
string s ="test";
}
}
12
Dobzhansky 2009-02-25
  • 打赏
  • 举报
回复
基本有 2 点:

1. 托管对象的内存结构不是公开的, 实现机制会变化, 引用中无需关心.
2. 为支持托管机制, 在传统(C++)实现前提下, 加入一个头部.
hebeijg 2009-02-25
  • 打赏
  • 举报
回复
谢谢各位

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧