说明:类的大小是指类的实例化对象的大小,用 sizeof 对类型名操作时,结果是该类型的对象的大小。计算原则如下:
C++
/*
说明:程序是在 64 位编译器下测试的
*/
#include <iostream>
using namespace std;
class A
{
private:
static int s_var; // 不影响类的大小
const int c_var; // 4 字节
int var; // 8 字节 4 + 4 (int) = 8
char var1; // 12 字节 8 + 1 (char) + 3 (填充) = 12
public:
A(int temp) : c_var(temp) {} // 不影响类的大小
~A() {} // 不影响类的大小
};
class B
{
};
int main()
{
A ex1(4);
B ex2;
cout << sizeof(ex1) << endl; // 12 字节
cout << sizeof(ex2) << endl; // 1 字节
return 0;
}
注意:虚函数的个数并不影响所占内存的大小,因为类对象的内存中只保存了指向虚函数表的指针。由于不同平台、不同编译器厂商所生成的虚表指针在内存中的布局是不同的,有些将虚表指针置于对象内存中的开头处,有些则置于结尾处。在 X64 GCC 编译器下,虚指针在类的开头出,我们可以通过偏移量获取。
程序示例,我们通过对象内存的开头处取出 vptr,并遍历对象虚函数表。
C++
/*
说明:程序是在 64 位编译器下测试的
*/
#include <iostream>
using namespace std;
class A
{
private:
static int s_var; // 不影响类的大小
const int c_var; // 4 字节
int var; // 8 字节 4 + 4 (int) = 8
char var1; // 12 字节 8 + 1 (char) + 3 (填充) = 12
public:
A(int temp) : c_var(temp) {} // 不影响类的大小
~A() {} // 不影响类的大小
virtual void f() { cout << "A::f" << endl; }
virtual void g() { cout << "A::g" << endl; }
virtual void h() { cout << "A::h" << endl; } // 24 字节 12 + 4 (填充) + 8 (指向虚函数的指针) = 24
};
typedef void (*func)(void);
void printVtable(unsigned long *vptr, int offset) {
func fn = (func)*((unsigned long*)(*vptr) + offset);
fn();
}
int main()
{
A ex1(4);
A *p;
cout << sizeof(p) << endl; // 8 字节 注意:指针所占的空间和指针指向的数据类型无关
cout << sizeof(ex1) << endl; // 24 字节
unsigned long* vPtr = (unsigned long*)(&ex1);
printVtable(vPtr, 0);
printVtable(vPtr, 1);
printVtable(vPtr, 2);
return 0;
}
/*
8
24
A::f
A::g
A::h
*/
C++
#include <iostream>
using namespace std;
class A
{
public:
int a;
};
class B : public A
{
public:
int b;
void bPrintf() {
std::cout << "This is class B" << "\n";
}
};
int main(){
A a;
B b;
cout<<sizeof(a)<<endl;
cout<<sizeof(b)<<endl;
return 0;
}
/*
4
8
*/
C++
#include <iostream>
using namespace std; // 采用 4 字节对齐
#pragma pack(4)
class A
{
public:
int a;
};
class B : virtual public A
{
public:
int b;
void bPrintf() {
std::cout << "This is class B" << "\n";}
};
class C : virtual public A
{
public:
int c;
void cPrintf() {
std::cout << "This is class C" << "\n";}
};
class D : public B, public C
{
public:
int d;
void dPrintf() {
std::cout << "This is class D" << "\n";}
};
int main(){
A a;
B b;
C c;
D d;
cout<<sizeof(a)<<endl;
cout<<sizeof(b)<<endl;
cout<<sizeof(c)<<endl;
cout<<sizeof(d)<<endl;
return 0;
}
/*
4
16
16
32
*/
我们可以看到:
实际的内存布局如下:
虚基类表的填充内容如下:
阅读量:2016
点赞量:0
收藏量:0