内存分区模型
- 代码区:存放函数体的二进制代码,由操作系统进行管理
- 全局区:存放全局变量和静态变量以及常量
- 栈区:由编译器自动分配释放,存放函数的参数值、局部变量等
- 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收
内存四区的意义:不同区域存放的数据,赋予不同的生命周期,灵活编程
程序运行前
代码区
存放 CPU 执行的机器指令。
特点
- 共享:对于频繁执行的程序,只需要在内存中有一份代码即可
- 只读:防止程序意外地修改它的指令
全局区
全局变量和静态变量存放在此,还包括常量区,字符串常量和其他常量也在此。
特点
- 该区域的数据在程序结束后由操作系统释放
程序运行后
栈区
由编译器自动分配释放,存放函数的参数值、局部变量等。
注意事项
不用返回局部变量的地址,栈区开辟的数据由编译器自动释放。
堆区
由程序员分配释放,若程序员不释放,程序结束时由操作系统回收。
在 C++ 中主要利用 new 在堆区开辟内存,用指针接收,指针是本质也是一个局部变量,放在栈上,但指针保存的数据是放在堆区。
对象动态建立和释放new和delete
new运算符动态分配堆内存
使用形式
指针变量=new 数据类型(常量);
指针变量=new 数据类型[表达式];
作用
从堆分配一块“类型”大小的存储空间,返回首地址
“常量”是初始化值,可缺省
创建数组对象时,不能为对象指定初始值
用new分配数组空间时不能指定初值。如果由于内存不足等原因而无法正常分配空间,则new会返回一个空指针NULL,用户可以根据该指针的值判断分配空间是否成功。
malloc不会调用类的构造函数,而new会调用类的构造函数
free不会调用类的析构函数,而delete会调用类的析构函数
delete运算符释放已分配的内存空间
使用形式
delete 指针变量;
delete[] 指针变量;
“指针变量”必须是一个new返回的指针
静态成员变量和成员函数
在C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。
类的静态成员,属于类,也属于对象,但终归属于类。
静态成员变量
static 静态成员
//声明
static 数据类型 成员变量;
//在类的内部 未分配空间
//初始化 定义和初始化,保证定义和初始化只进行一次
【因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的。】
数据类型 类名::静态数据成员=初值;
//在类的外部,不必再加static
//调用
类名::静态数据成员;
//属于整个类
类对象.静态数据成员;
//属于该对象
const static/static const 静态常量成员
声明的同时初始化,因为该变量被const修饰,称为常变量,只能进行一次初始化,不可变
1.static成员变量实现了同类对象间信息共享
2.static成员类外存储,求类大小,并不包括在内
3.static成员是命名空间属于类的全局变量,并存储在data区
4.static成员只能类外初始化
5.可以通过类名访问(无对象生成时亦可),也可以通过对象访问
静态成员函数
//声明
static 函数声明
//调用
类名::函数调用
类对象.函数调用
static成员函数只能返回static成员变量。(static成员函数属于整个类,而非某个对象,static成员变量也是如此)
1.静态成员函数的意义,不在于信息共享,数据沟通,而在于管理静态数据成员,完成对静态数据成员的封装。
2.静态成员函数只能访问静态数据成员。原因:非静态成员函数,在调用时this指针当作参数传进。而静态成员函数属于类,而不属于对象,没有this指针。
类内静态成员函数没有this指针,this指针只能用于非静态成员函数内部。
编译器对属性和方法的处理机制
静态成员占多大空间
运行结果:12 12 12 12
为什么sizeof(C2)=12?
class C2 {
public:
int i;
int j;
int k;
static int m; //类的大小和静态成员无关,静态成员存储于全局数据区中
public:
int getK() const { //类的大小和成员函数无关,成员函数存储于代码段中
return k;
}
void setK(int val) {
k = val;
}
};
为什么sizeof(S2)=12?
struct S2 {
int i;
int j;
int k;
static int m; 结构体的大小与静态成员无关
};
处理机制
C++类对象中的成员变量和成员函数是分开存储的。
成员变量
普通成员变量
存储于对象中,与struct变量有相同的内存布局和字节对齐方式。
静态成员变量
存储于全局数据区中。
成员函数
存储于代码段中。
C++编译器对类的成员的内部处理机制类似如下
1、C++类对象中的成员变量和成员函数是分开存储的。C语言中的内存四区模型仍然有效!
2、C++中类的普通成员函数都隐式包含一个指向当前对象的this指针。
3、静态成员函数、成员变量属于类
4、静态成员函数与普通成员函数的区别
静态成员函数不包含指向具体对象的指针
普通成员函数包含一个指向具体对象的指针