继承成员的访问权限是否会影响C++类的整体大小?
问题:类成员访问权限为何会影响sizeof的结果?
运行以下C++代码时,base类和派生类c1的sizeof结果均为32:
#include "iostream" #include "string" using namespace std; class base{ //public: int a; double b; void * c; char d; }; class c1 : base{ //public: int a; }; int main() { cout << sizeof(base) << endl; cout << sizeof(c1) << endl; return 0; }
但取消base类和c1类中public:的注释后,派生类c1的sizeof结果变为40。该现象可在GCC中复现,请问为何成员变量的访问权限会影响类的整体大小?
解答
这是GCC编译器针对类内存布局的访问控制区段优化规则导致的,核心逻辑和内存对齐、访问区段的划分有关:
1. 先看base类的大小计算(64位系统下)
base的成员依次是:
int a:占4字节double b:占8字节,因对齐要求,a后面要填充4字节才能对齐到8字节的起始地址void* c:占8字节,无需额外填充char d:占1字节,后面需要填充7字节,让整个类的大小对齐到最大成员的对齐单位(8字节)
加起来总大小是:4+4(填充)+8+8+1+7(填充)=32字节,这就是sizeof(base)=32的原因。
2. 默认私有继承+同访问区段的情况
当base和c1的成员都默认是private时:
c1继承base是私有继承(类默认继承权限为private),基类的所有成员在c1里都属于private区段c1自己的int a也是private成员,和基类继承来的成员属于同一个访问控制区段
GCC会对同一区段的成员做紧凑布局优化:把c1的int a直接塞进base末尾的7字节填充空间里,不需要额外占用空间,所以sizeof(c1)还是32字节。
3. 开启public:后的情况
取消public:注释后:
base的成员变为public,但c1默认私有继承base,所以基类的public成员在c1里会被降级为private区段c1自己的int a是public成员,属于单独的public区段
GCC对不同访问控制区段的成员会分开布局,而且区段之间要按照最大对齐单位(8字节)填充:
- 第一个区段是继承自
base的32字节内容 - 第二个区段是
c1的int a(4字节),后面需要填充4字节来对齐到8字节 - 总大小就是32+4+4=40字节
简单说:同一访问区段的成员可以共享填充空隙,不同区段则必须分开占空间,这就是访问权限影响类大小的核心原因。
内容的提问来源于stack exchange,提问作者PkDrew
相关产品推荐
相关产品推荐

