类对象所占用的空间可以用sizeof()函数获取,在C++对象模型中,类对象所占用的空间规则如下:
(1) 空类占1字节,以使该类对象在内存得以配置一个地址。
(2) 对象所占用的空间由3个因素决定:非静态成员变量、虚函数、字节填充。
我们可以再细化:
(2.1) 静态成员变量,成员函数(静态、非静态)都不计算在sizeof()里。
(2.2) 指针占用的内存大小是固定的,4字节或8字节,具体取决于操作系统是32位还是64位。
(2.3) 虚函数不计算在对象的sizeof内,但虚函数会让对象的sizeof增加4个字节(64位操作系统中是8个字节),因为这时会增加1个虚函数表指针。
(2.4) 字节对齐。
1、空对象占1个字节
class A {
public:
};
int main() {
A a;
std::cout << sizeof(a) << std::endl;
return 0;
}
输出1,说明空对象至少占1字节的内存空间。
2、char变量占1个字节
我们再把这个class A修改一下,添加一个char变量,看看这时对象是多少个字节?
class A {
public:
char c1;
};
这时依然输出1,那么这个1字节空间是谁的呢?是char c1的。
我们可以再添加1个char c2,看一下这时的对象大小,发现变成了2。所以,我们可以得出1个结论:成员变量char占1个字节。
3、函数不占字节
我们再把这个class A修改一下,添加1个函数,看看这时对象是多少个字节?
class A {
public:
char c1;
void func1(){ }
};
发现对象的大小依然是1,所以我们可以得出1个结论:类中的成员函数是不占用类对象内存空间的。
4、指针变量占4个字节(32位环境)
我们给类A增加1个指针变量,并且把char变量删除,看看现在对象的大小。
class A {
public:
void func1() { }
public:
int* pI1;
};
这里说明一下,为了简单起见,我们把编译环境统一为x86(32位)。这时输出4,说明:指针占4个字节。不管什么类型的指针,都是4个字节哦。
(如果是64位环境,则指针变量占8个字节)
5、字节填充
我们再把char变量添加进去,看现在的对象大小是多少?
class A {
public:
void func1() { }
public:
char c1;
int* pI1;
};
照理说char的大小是1,指针的大小是4,对象的大小应该是5吧。但实际的输出确是8。
为什么呢?
为了访问速度和性能考虑,这时系统会给char分配4个字节 -- 这叫字节对齐,都往4个字节对齐。
6、虚函数
前面我们数过函数是不占用类对象空间的,那么给类添加1个虚函数后会怎样呢?我们把代码修改一下:
class A {
public:
virtual void func1() { }
public:
char c1;
int* pI1;
};
此时输出12,也就是说1个虚函数让对象增加了4个字节。这是因为增加了1个虚函数指针的原因。
现在类对象的布局应该是这样的:
7、C++基本数据类型的大小
不管是32位还是64位,C++基本数据类型的大小是不变的。
数据类型 | 字节数 |
bool | 1 |
char | 1 |
int | 4 |
unsigned int | 4 |
short int | 2 |
long int | 8 |
float | 4 |
double | 8 |