frendguo's blog

关于C++中对象在内存中的大小

关于 C++ 类的大小,这里需要首先说明,C++ 类只是个声明,此处讨论的都是指该类的对象。

测试环境:Bash on Ubuntu on Windows (16.04 64bit) + g++(5.4.0 20160609)

关于 C++ 对象在内存中的大小,通常有以下几种情况:

  • 空类对象也会占用 1 个字节
  • 编译器为了方便 CPU 进行计算,通常会牵涉到 内存对齐(data alignment),也会影响类对象的大小
  • 为了支持虚函数,也需要产生额外的负担
  • 虚继承也会带来额外的负担
  • 非静态成员变量大小的总和
  • C++ 位域的计算

1. 空类对象

先直接上结果:

空类对象大小是 1 。因为如果空类对象的大小是 0 的话,那就不好表示类对象在内存中的位置了。所以编译器会给空类对象增加一个字节的数据用来定位类对象的位置。当然这里有木有成员函数,对结果都是木有影响的。看下图:

2.关于内存对齐

有关内存对齐可以看这边 MSDN 文档:点这里》》

我们还是先看个例子:

class B
{
private:
    char c;
    int i;
    short s;
    long l;

};

我们首先想到的肯定是把这几个类型的大小加起来就是这个类对象的大小了。

没错,正常情况下会这样的。但是因为编译器需要给 CPU 计算优化,所以引入了内存对齐(data alignment)。

所以实际上这个类对象的大小是 char(1) + pad(3) + int(4) + short(4) + long(8) = 20, 最后还有个类的对齐,也就是类最后的大小需要是类成员最大值的整数倍,这里也就是 8 的整数倍。所以最终类对象的大小应该是 24;验证后也是这样的:

3.类成员中包含虚函数

有关虚函数,我们肯定会想到 vptr 和 vtbl 这两个指针。在类成员中包含虚函数成员的情况下,this 指针的前四个字节也就是 vptr ,然后 vptr 是指向当前类对象的 vtbl 的。所以也就不难理解为什么类中包含虚函数成员的情况下会多四个字节的情况了。以下仍是一个测试:

class C
{
public:
    virtual void fun() { cout << "hello world!" << endl; }
    int i;
    long l;
};

该类对象的大小应该是:vptr(8) + int(4) + pad(4) + long(8) = 24,运行下,结果如下:

4. 类的虚继承

有关什么是虚继承,不是我们这里讨论的话题,不懂的可以看这里》》》

还是先看个例子:

class Base
{
public:
    char c;
};

class A : virtual public Base
{

};

class B : virtual public Base
{

};

class C : public A, public B
{

};

这次我们先看看结果(注:测试环境在 64bit 环境下)

对于 Base 的大小应该没什么可以说的,很简单就是 1 ;

对于 A 和 B 类对象的大小,根据虚继承的概念,我们知道 A (B) 类对象里面是有个指向虚基类表的指针的,然后再加上继承过来的 char 成员变量,并且加上内存对齐,于是很容易得到:vptr(8) + char(1) + pad(7) = 16;

对于 C 类对象的大小,这里我们还是先弄清楚菱形继承中的最派生类 (C) 中的构成,C 在继承 A 和 B 的时候,将 A 和 B 的 vptr 都继承下来了,再加上 Base 中的 char ,最后再加上内存对齐,就得到了:2 * vptr(8) + char(1) + pad(7) = 24;

5.位域

此部分参考MSDN文档:看这里》》

 

Happy Coding!o(* ̄▽ ̄*)o

Add comment

Loading