💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃个人主页 :阿然成长日记 👈点击可跳转
📆 个人专栏: 🔹数据结构与算法🔹C语言进阶
🚩 不能则学,不知则问,耻于问人,决无长进
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍
文章目录
- 一、 类和对象的关系
- 二、类在内存中的存储方式
- 1.类的构成
- 2.内存分布
- 3.分析存储方式
- 三、类对象大小的计算
- 1.案例引入
- 2.计算方法:
- 3.分析下面案例:
- 4.空类大小的计算
- 补充:
一、 类和对象的关系
类
:类是一个抽象概念,是一类具有相同特征的事物的统称,不是具体存在的,对象
:对象是一种具体概念,对象是具体事物的实体。
类和对象的关系:简单来说类是抽象的,不占用内存,而对象是具体的,占用存储空间。类->对象
【一对多的关系】。一个类的实例化就是一个对象的创建。
举一个例子:大学生是一个类,那么大学生小明就是其中的一个对象大学生张三也是一个对象。
二、类在内存中的存储方式
1.类的构成
首先,一个类分为两个部分,成员变量
+成员函数
。
2.内存分布
对于成员变量来说,我们每次创建一个对象,肯定是要给他初始化不同的值(如果传相同的值,有啥意义呢),那么,成员变量是一定要进行另外的存储的。对于成员函数来说,我们使用的是同一个函数,用实现同一个操作,就没有必要在对象中额外拷贝一份函数存储到内存中来,所以,对象想要使用类中的函数直接去调用公共代码区的函数就可以了。
例如:就好比说一个小区,睡觉的时候你肯定要有自己的床,每个人都会有自己的小床,但是打篮球的时候就没有必要建立自己的篮球场,大家可以共同使用同一个篮球场。也就是说对于成员函数的存储我们在对象中只需要保存它的一份地址,直接调用即可。
用图来表示:
3.分析存储方式
上图就是类实例化的对象在内存中的分布情况,其中值得注意的是成员函数并不存储于每个对象中,而是多个对象共享函数代码,函数存在于公共内存中,由一个函数表统一管理,函数表中存储着每个函数的地址。当我们在对象中去调用函数时,通过类中的一个指针,找到函数表,在从中找到对应的地址,从而进行调用。
注意点:内联函数(也就是函数的定义和声明都在类中)调用时效率很高,因为它在编译时就已经在原位置进行替换,不需要在函数表中去查找调用。所以,这也就是我们为什么提倡把一些简短的,调用频繁的函数声明为inline(内联函数)。
三、类对象大小的计算
1.案例引入
例如:如下代码
class Data
{
public:
void Print()
{
cout << _year << _month << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
这个给Data类的大小计算结果是12.那我们可以想一下为什么是12而不是别的,类的大小是怎么计算的,带着这个问题我们向下学习-><-
2.计算方法:
通过上面类对象在内存中的存储的学习,我们知道:
- 类本身不占用内存,实例化出的对象 ,占用实际的物理空间。
- 成员变量存在对象中
- 成员函数的地址不在对象中。
类的大小计算 == 结构体内存对齐
如果你忘记了结构体大小,请看我的这篇博客:结构体内存对齐
3.分析下面案例:
例如:计算下面类的大小
#include<iostream>
using namespace std;
class Data
{
public:
void Init(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Data d1;
cout << sizeof(Data) << endl;
}
运行结果
上面代码类对象的大小计算,只需要看成员变量那一块地方。为了减小内存的开支,我们需要合理安排类成员变量的先后顺序。
4.空类大小的计算
class T
{
};
int main()
{
cout << sizeof(T) << endl;
}
无成员变量的类(里面可能有成员函数),对象开一个字节,因为空类可以实例化,实例化必然在内存中占有一个位置,因此,编译器为其优化为一个字节大小。
补充:
由于还没有学习虚函数,继承等等,对象的大小的计算不是很完整,等下来学习了之后,在做整理!!