C++ 类的大小计算

class A
{
};

class B
{
	char ch;
	virtual void func0()  {  }
};

class C
{
	char ch1;
	char ch2;
	virtual void func()  {  }
	virtual void func1()  {  }
};

class D : public A, public C
{
	int d;
	virtual void func()  {  }
	virtual void func1()  {  }
};

class E : public B, public C
{
public:
	int e;
	virtual void func0()  {  }
	virtual void func1()  {  }
	//子类里(E)没有实现func(),所以在E的子类里B的vfptr指向C的func()和E的func1()
	virtual void func123()  {  }
}


int main()
{
        //result=1,空类,大小为1
        cout << "A=" << sizeof(A) << endl;
        
        //result=8,4(vfptr,4)+4(char ch,内存对齐,4) = 8       
	cout << "B=" << sizeof(B) << endl; 
	  
	//result=8 , 4(vfptr,4)+4(char ch1,char ch2,内存对齐,4) = 8  
	cout << "C=" << sizeof(C) << endl;    
	
	//result=12, 4(类D的vfptr,4)+4(存在基类的char ch1,char ch2,内存对齐,4)+4(int d) = 12
	D obj_d; //首先VPTR指向的虚函数表中保存的是类D中的两个虚函数的地址
	cout << "D=" << sizeof(obj_d) << endl;    
	
	
	//result=20,(多继承)继承多少个有虚函数的类,就有多少个虚函数指针,也即这几个虚函数指针组成了自己的vfptr(编译器不再单独给自己的虚函数插vfptr)
	//4(B的vfptr)+4(char ch)+4(C的vfptr)+4(C中 char ch1,char ch2)+4(E 中int d) = 20
	//这个可以从调试下看出来
	E obj_e;
	obj_e.e = 123;
	cout << "E=" << sizeof(obj_e) << endl;    

        return 0;
}


### 大小计算C++中,大小是指其**实例化对象**所占用的内存大小本身作为一种型定义,并不具有实际的大小,只有当被实例化为对象时,才会占用内存空间。大小主要由其非静态数据成员决定,而成员函数、静态成员(包括静态数据成员和静态成员函数)不会影响大小[^1]。 #### 大小计算的基本原则 1. **普通数据成员**:大小主要由其非静态数据成员决定。 2. **成员函数**:无论是普通成员函数还是静态成员函数,它们都不计入大小。 3. **静态数据成员**:静态数据成员属于整个,而不是的实例,因此也不计入大小。 4. **虚函数**:如果中包含虚函数,编译器会为添加一个虚函数表指针(vptr),这会增加大小。虚函数表指针的大小通常为指针的大小(如32位系统为4字节,64位系统为8字节)[^1]。 5. **虚继承**:虚继承会引入虚基表指针(vbptr),这也会增加大小。 6. **空**:空大小是一个特殊情况,即使没有任何成员变量,空大小也为1字节。这是为了确保的每个实例在内存中都有唯一的地址,以支持对象的唯一标识[^1]。 #### 内存对齐原则 大小计算还遵循结构体的对齐原则。编译器会对数据成员进行内存对齐,以提高访问效率。这意味着大小可能会大于其所有数据成员的总和。例如: ```cpp class Example { char a; int b; short c; }; ``` 在某些平台上,由于内存对齐的要求,`Example` 大小可能为12字节(而不是 `1 + 4 + 2 = 7` 字节)。 #### 示例代码 以下代码展示了如何计算大小: ```cpp #include <iostream> class Empty {}; class Base { int a; virtual void func() {} }; class Derived : public Base { double b; }; int main() { std::cout << "Size of Empty: " << sizeof(Empty) << " bytes" << std::endl; // 输出1字节 std::cout << "Size of Base: " << sizeof(Base) << " bytes" << std::endl; // 包含虚函数,可能输出8字节(32位系统)或16字节(64位系统) std::cout << "Size of Derived: " << sizeof(Derived) << " bytes" << std::endl; // 包含Base和double,可能输出16字节(64位系统) return 0; } ``` #### 多态大小 对于包含虚函数的,编译器会为其添加一个虚函数表指针(vptr),这会增加大小。例如: ```cpp class MyClass { int x; virtual void method() {} }; ``` 在64位系统上,`MyClass` 的大小为16字节(`int` 占4字节,vptr 占8字节,加上内存对齐)。 #### 虚继承的大小 虚继承会引入虚基表指针(vbptr),增加大小。例如: ```cpp class Base { int a; }; class Derived : virtual public Base { int b; }; ``` 在这种情况下,`Derived` 大小将包含一个虚基表指针(vbptr),其大小通常为指针的大小(如64位系统为8字节)加上 `int a` 和 `int b` 的大小。 ### 相关问题 1. C++中如何计算包含虚函数的大小? 2. C++中虚继承对大小有何影响? 3. C++中空大小为什么是1字节? 4. C++中如何优化的内存占用? 5. C++大小与结构体的对齐原则有何关系?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值