免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3945 | 回复: 9
打印 上一主题 下一主题

请问一个类的大小是什么? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-08-15 17:47 |只看该作者 |倒序浏览
我写了几个乱七八糟的类,都用sizeof()测了一下:
  1. class Aclass
  2. {
  3. public:
  4.         Aclass();
  5.         virtual ~Aclass();
  6. };

  7. class B;

  8. class A
  9. {
  10.         B *b;
  11. public:
  12.         A();
  13.         void        arrPara(int t[]);
  14.         static void        testmap();
  15.         static std::string        addSplit(std::string name[]);
  16. };

  17. class Base
  18. {
  19. public:
  20.         int k;
  21.        
  22.         Base();
  23.         virtual ~Base();
  24.        
  25.         virtual void func() = 0;
  26. };

  27. class User
  28. {
  29. public:
  30.         int id;
  31.         std::string name;
  32.        
  33.         User();
  34.         virtual ~User();
  35.        
  36.         operator bool() const {if (id) return true; return false;}
  37. };
复制代码

简单测试:
  1. void sizeofAclass()
  2. {
  3.         printf("size of class Base = %d\n", sizeof(Base));
  4.         printf("size of int = %d\n", sizeof(int));
  5.         printf("size of class User = %d\n", sizeof(User));
  6.         printf("size of class Aclass = %d\n", sizeof(Aclass));
  7.         printf("size of class A = %d\n", sizeof(A));
  8. }
  9. $ ./test
  10. size of class Base = 8
  11. size of int = 4
  12. size of class User = 12
  13. size of class Aclass = 4
  14. size of class A = 4
复制代码

请问能否帮忙解释一下,
我知道c中的struct的大小就是其中的变量之和,但c++类的大小为什么是上述的情况?
谢谢~

论坛徽章:
0
2 [报告]
发表于 2006-08-15 17:50 |只看该作者
考虑数据成员的大小.
考虑性能优化采用的地址对齐
考虑隐含的虚表指针成员

论坛徽章:
0
3 [报告]
发表于 2006-08-15 17:57 |只看该作者
谢谢楼上的,
您的意思是说类的大小是不确定的?
那如果我要自己控制内存,申请了一段固定的内存空间,该如何把类的对象定义在这段内存之中?以及对象占了多大空间?
我主要是不清楚类能不能像struct一样方便地让自己控制它的内存

论坛徽章:
0
4 [报告]
发表于 2006-08-15 18:07 |只看该作者
您的意思是说类的大小是不确定的?

大小当然是确定的,但这个大小上是上面几个因素的综合效果.
class className
{
.....
};
每个类的大小都是sizeof(className);


那如果我要自己控制内存,申请了一段固定的内存空间,该如何把类的对象定义在这段内存之中?
你所说的,在c++里面被称为placement new,你可以google一下
或者我记得在Effective C++ & More Effective C++里有介绍

我主要是不清楚类能不能像struct一样方便地让自己控制它的内存
c语言里面struct的大小也要考虑地址对齐的吧.
有可行性,但比较麻烦,一般很少这样做.

论坛徽章:
0
5 [报告]
发表于 2006-08-15 18:11 |只看该作者
再次感谢,
下班先回家了~

论坛徽章:
0
6 [报告]
发表于 2006-08-16 10:59 |只看该作者
placement new 我有用过,就是把结构定义在已申请的内存中
如下例:
  1. #include <new>
  2. struct ff {
  3.         int num;
  4.         char str[20];
  5. };
  6. char buff1[100];
  7. char buff2[100];
  8. int main()
  9. {
  10.         ff *p1;
  11.         int *p2;

  12.         p1 = new (buff1) ff;
  13.         p2 = new (buff2) int[20];

  14.         return 0;
  15. }
复制代码

placement new 就是我想要的,
现在是想把类的对象也定义到自己的内存中,
但是对“类的大小”概念模糊

比如我上面申明的几个类,
Aclass类的大小是4,我把析构函数virtual ~Aclass()改为~Aclass(),它的大小就变成1了,那这1个字节里面放什么东西?
A类里面只有一个指针,所以他的大小是4?
Base类的大小 = sizeof(虚表指针) + sizeof(int) ?
User类的大小 = sizeof(虚表指针) + sizeof(int) + sizeof(std::string) ?由User类定义的对象的大小该不会因name的内容增加而变大吧?
期待耐心的解释~谢谢先~

论坛徽章:
0
7 [报告]
发表于 2006-08-16 12:18 |只看该作者

  1. class Aclass
  2. {
  3. public:
  4.         Aclass();
  5.         virtual ~Aclass();
  6. };
复制代码

AClass的大小为4是因为你的析构函数被定义为虚拟的,这就引入了一个隐含的虚表指针成员,32位平台上,指针的大小为4字节;
当你将virtual ~Aclass改为~Aclass时,Aclass中就没有定义虚函数表,自然也就没有虚表指针成员了.这种情况下,由于你的类没有定义数据成员,也就是说他没有占据存储空间,但是由于当创建一个对象时,要标识一个对象,必须通过给它分配存储空间来引用对象,两者权衡之下,就给它分配了一个字节的存储空间.


  1. class User
  2. {
  3. public:
  4.         int id;
  5.         std::string name;
  6.         
  7.         User();
  8.         virtual ~User();
  9.         
  10.         operator bool() const {if (id) return true; return false;}
  11. };
复制代码


你可以这样考虑,对于普通的类型的成员,比如所int,double,float等,它占据的尺寸是该类型变量所对应的大小与与编译器相关的地址对齐的综合效果,
如果是一个某一类型的指针或引用类型的变量,它的大小在32位平台上就是4个字节.

任何一个类,最终总要归结到这些基础数据类型上去.
比如string类,要实现它的功能,它里面就定义了一个char*类型的指针,指向数据存储区.

  1. class string
  2. {
  3. private:
  4.     char* data;     //某一个缓冲区的指针
  5. }
复制代码

上面的应当就是string类型的定义,它的尺寸应当为4字节.

其他的类的尺寸就是由它所包容的类的实例的尺寸一成一层累加起来的(考虑对齐因素);string的尺寸与与其相关联的存储区的大小没有关系.

Inside c++ object model里面有介绍;

placement new比较麻烦,得重载new delete new[] delete[],需求是如何产生的?

论坛徽章:
0
8 [报告]
发表于 2006-08-16 12:41 |只看该作者
首先非常感谢~
placement new不需要重载吧?只要 #include <new> 就好了
有个无限循环的线程,每次循环总要声明几个局部变量,
于是用常规的new申请一个较大的空间,用placement new把这些变量定义在大空间里面,省得用系统栈或者系统堆产生碎片。
我试了一些字符串的局部变量没有问题,现在想把一些局部的类对象也放进去看有没有危险。。

placement new不需要(不能)delete,但要自己计算new在内存中的具体偏移量,所以要搞清楚“类(对象?)的大小”

论坛徽章:
0
9 [报告]
发表于 2006-08-16 14:40 |只看该作者
placement new不需要重载吧

等你出错的时候再来讨论这个问题好了.

论坛徽章:
0
10 [报告]
发表于 2006-08-16 16:12 |只看该作者
晕,明明就是可以的。。
我要加你为好友,冷暖-_-
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP