对象内存模型
内容简介
C++ 对象中真正占用对象空间的是非静态成员变量。成员函数、静态成员函数和静态成员变量不存放在每个对象内部。
基本规则
- 非静态成员变量属于对象。
- 成员函数不属于某个对象的存储空间。
- 静态成员变量属于类,不属于对象。
- 空对象也至少占 1 字节,保证不同对象有不同地址。
示例:
class Empty {
};
class Person {
public:
int age;
void func() {}
static void static_func() {}
static int count;
};
int Person::count = 0;
std::cout << sizeof(Empty) << '\n';
std::cout << sizeof(Person) << '\n';为什么空对象占 1 字节
如果空对象大小是 0,两个不同对象可能有相同地址。C++ 要保证不同对象能被区分,因此空对象至少占 1 字节。
Empty a;
Empty b;
std::cout << (&a == &b) << '\n'; // 通常为 false成员函数在哪里
成员函数本质上是代码,不为每个对象复制一份。非静态成员函数通过隐藏的 this 指针知道自己操作哪个对象。
class Person {
public:
void set_age(int age)
{
this->age = age;
}
private:
int age = 0;
};最佳代码实践
- 不要以为类里函数多,对象就一定变大。
- 关注对象大小时,重点看非静态数据成员、对齐和虚函数。
- 对象是否有虚函数会影响对象布局,通常会引入虚表指针。
错误用法
class Person {
public:
static int count;
};
Person p;
std::cout << sizeof(p) << '\n'; // 不要以为 count 在 p 里面注意事项
- 对象布局会受编译器、ABI、对齐规则影响。
- 多态对象布局更复杂,见 cpp多态。
- 平凡对象、标准布局类型后续可以作为单独主题补充。
学习路径
- 上一节:cpp静态成员
- 当前阶段:cppOOP
- 下一节:cppconst成员函数和常对象