C++是一种可以操作内存的编程语言,虽然说类对象的内存布局会随着编译器以及运行环境的影响而受到变化。但是通过一些简单的分析还是可以加深自己对语言本身的理解。
我们来看几种情况:读者可以不看下面的具体分析,只是询问一下自己,它们的大小,你知道吗?
- 没有任何数据成员的类
- 只有成员函数但没有数据成员的类
- 拥有一个整形数的类
- 拥有一个整形和字符整形(char)的类
- 带有虚函数的类
- 继承拥有虚函数父类的子类
先贴代码:
#include <iostream>
#include <string>
class Foo
{
};
class FooWithFunction
{
};
class FooWithInt
{
int i;
};
class FooWithIntChar
{
int i;
char c;
};
class Test
{
public:
virtual void foo() {}
};
class Derived : public Test
{
public:
virtual void derivedFoo() {}
};
int main()
{
std::cout << "Foo size: \t\t\t" << sizeof(Foo) << std::endl;
std::cout << "FooWithFunction size: \t\t" << sizeof(FooWithFunction) << std::endl;
std::cout << "FooWithInt size: \t\t" << sizeof(FooWithInt) << std::endl;
std::cout << "FooWithIntChar size: \t\t" << sizeof(FooWithIntChar) << std::endl;
std::cout << "Test with virtual function: \t" << sizeof(Test) << std::endl;
std::cout << "Pointer size: \t\t\t" << sizeof(int *) << std::endl;
Derived d;
std::cout << "Derived object size: \t\t" << sizeof(d) << std::endl;
return 0;
}
Foo size: 1
FooWithFunction size: 1
FooWithInt size: 4
FooWithIntChar size: 8
Test with virtual function: 8
Pointer size: 8
Derived object size: 8
注,以上代码在Linux 64 bit系统上使用GCC编译通过
为什么是这样的呢?
- 对于没有任何类成员的类,编译器通常只是为了标记它,分配最小的空间。至于为什么不是0,也不是另一个更大的数,我觉得是为了性能和实现的妥协。
- 只有成员函数,而没有数据成员,这不会增加对象的内存大小。成员函数所占据的空间都在代码段上。和数据不在一起。
- 这里的整形数是4个字节,可能在不同的平台上会不一样。
- 在默认的情况下,编译器会做一些内存的对齐,所以Char被撑大到四个字节。
- 对象内部会包含一个虚函数指针,在64位系统中,一个指针是需要8个字节来表示的。
- 继承如果不增加数据成员的情况下,并不会增加对象的大小,同样包含一个虚函数指针。
这里其实只是C++对象内存模型的一个很简要描述,还有一些延伸的问题。
- 多继承情况下,对象的内存又会变成什么样呢?
- 虚继承场景
...