C++的字节对齐
C++的字节对齐是其独有的。
至于为什么有字节对齐,这里不述,一句话,为了提高程序的读写性能,且对齐的大小可编码。
字节对齐的三个准则:
- 变量的首地址能够被其对齐字节数大小整除
- 每个成员相对首地址的偏移量都是该成员大小的整数倍,如果不是,那么前一个成员变量补齐
- 总大小是最大成员大小的整数倍
下面的测试代码是对三个准则的详细说明:
struct POINTER { void* ptr; }; struct A { char a; }; struct B { char a; char b; }; struct C { char a; int b; long c; }; struct D { long c; char a; int b; }; struct E { char a; long c; int b; }; struct F { char a; long c; char b; }; struct G { char a; long c; F b; }; struct H { char a; char b; short c; }; struct I { char a; char b; int c; }; struct EMPTY_CLASS { }; struct EMPTY_CLASS_WITH_VIRTUAL { virtual ~EMPTY_CLASS_WITH_VIRTUAL(){} }; #define CALC_STRCUT_SIZE(T) \ std::cout <<"size of type " << #T << " is " << sizeof(T) << std::endl; int main(int argc, char** argv) { CALC_STRCUT_SIZE(A) CALC_STRCUT_SIZE(B) CALC_STRCUT_SIZE(C) CALC_STRCUT_SIZE(D) CALC_STRCUT_SIZE(E) CALC_STRCUT_SIZE(F) CALC_STRCUT_SIZE(G) CALC_STRCUT_SIZE(H) CALC_STRCUT_SIZE(I) CALC_STRCUT_SIZE(EMPTY_CLASS) CALC_STRCUT_SIZE(EMPTY_CLASS_WITH_VIRTUAL) CALC_STRCUT_SIZE(char*) CALC_STRCUT_SIZE(short*) CALC_STRCUT_SIZE(int*) CALC_STRCUT_SIZE(long*) CALC_STRCUT_SIZE(void*) CALC_STRCUT_SIZE(F*) CALC_STRCUT_SIZE(POINTER) return 0; }
下面是上述程序的运行结果:
size of type A is 1 size of type B is 2 size of type C is 16 size of type D is 16 size of type E is 24 size of type F is 24 size of type G is 40 size of type H is 4 size of type I is 8 size of type EMPTY_CLASS is 1 size of type EMPTY_CLASS_WITH_VIRTUAL is 8 size of type char* is 8 size of type short* is 8 size of type int* is 8 size of type long* is 8 size of type void* is 8 size of type F* is 8 size of type POINTER is 8
字节对齐准则在C和C++都符合。
但是这里需要注意两点,这个是C++独有的:
- 一个空类,即没有任何非静态成员变量和虚函数的类其大小是1。
- 包含了虚函数的类,其实际包含有个隐性的虚表指针(vbptr)。
上述两点准确的来说,不是内存对齐的特性。
上述两个大特性是C++面试中最常见的!但是,对于实际编程其实没什么多大用处,除非涉及到极致的性能优化!