C++ 类的实例化对象大小

实习生笔试面试时碰到过多次的问题,通过运行代码记录一下结论。测试平台为64位。

空类

1
2
3
4
5
6
class A {};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
return 0;
}
1
sizeof(a) is 1

空类的大小为1

只含有构造函数、析构函数、成员函数的类

1
2
3
4
5
6
7
8
9
10
11
class A {
public:
A() {};
~A() {};
void fun() {};
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
return 0;
}
1
sizeof(a) is 1

大小与构造函数、析构函数、成员函数无关

含有成员变量的类

需要考虑对齐

C++中数据类型占据字节长度
| 数据类型 | 大小 |
| —— | —- |
| char | 1 |
| bool | 1 |
| short | 2 |
| int | 4 |
| float | 4 |
| double | 8 |

简单类

1
2
3
4
5
6
7
8
9
10
class A {
public:
char ch;
int num;
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
return 0;
}
1
sizeof(a) is 8

size = 1(char) + 3(padding) + 4(int) = 8

成员变量不同的顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A {
public:
double d;
char ch;
int num;
};
class B {
public:
char ch;
double d;
int num;
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
B b;
cout << "sizeof(b) is " << sizeof(b) << endl;
return 0;
}
1
2
sizeof(a) is 16
sizeof(b) is 24

大小为占用最大空间的类型所占用的字节数的倍数

sizeof(a) = 8(double) + 1(char) + 3(padding) + 4(int) = 16

sizeof(b) = 1(char) + 7(padding) + 8(double) + 4(int) + 4(padding) = 24

指针

1
2
3
4
5
6
7
8
9
class A {
public:
int* p;
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
return 0;
}
1
sizeof(a) is 8

指针变量的大小与机器平台有关,64位机器为8个字节

静态成员变量

1
2
3
4
5
6
7
8
9
10
11
class A {
public:
char ch;
int num;
static int count;
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
return 0;
}
1
sizeof(a) is 8

静态成员变量不影响

虚函数

1
2
3
4
5
6
7
8
9
10
class A {
public:
virtual void fun1() {}
virtual void fun2() {}
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
return 0;
}
1
sizeof(a) is 8

有虚函数时,占用个内存会包含一个虚表指针(64位大小为8字节),且不论虚函数的个数多少只有一个

虚表指针放在对象内存的起始位置

继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A {
public:
char ch1;
};
class B:public A{
public:
char ch2;
int num;
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
B b;
cout << "sizeof(b) is " << sizeof(b) << endl;
return 0;
}
1
2
sizeof(a) is 1
sizeof(b) is 8

大小叠加并考虑对齐,基类成员在前

同名变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A {
public:
int num;
};
class B:public A{
public:
int num;
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
B b;
cout << "sizeof(b) is " << sizeof(b) << endl;
return 0;
}
1
2
sizeof(a) is 4
sizeof(b) is 8

含有虚函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A {
public:
virtual void fun1() {}
};
class B:public A{
public:
virtual void fun2() {}
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
B b;
cout << "sizeof(b) is " << sizeof(b) << endl;
return 0;
}
1
2
sizeof(a) is 8
sizeof(b) is 8

基类有虚函数,派生类也有虚函数,在虚表指针指向的虚表中添加一个函数指针,所以派生类仍仅有一个虚表指针

虚继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A {
public:
int num;
virtual void fun1() {}
};
class B:virtual public A{
public:
virtual void fun2() {}
};
int main() {
A a;
cout << "sizeof(a) is " << sizeof(a) << endl;
B b;
cout << "sizeof(b) is " << sizeof(b) << endl;
return 0;
}
1
2
sizeof(a) is 16
sizeof(b) is 24

与编译器有关,测试使用的是gcc

sizeof(b) = vptr_b(8) + sizeof(a) = 24

其他编译器还会有子类指向父类的指针