1、代码区
代码区的特点:
1.只读:防止程序运行时修改其执行代码,有助于程序稳定和安全性。
2.共享:多个程序运行可共享同一份代码区,以节省内存。
3.固定大小:代码区的大小在程序编译连接时就已经确定,运行时不会改变。
4.效率:由于代码区通常加载在连续的内存地址中,并且是只读的,这有利于CPU的指令缓存,从而提高程序执行的效率。
使用方法:
#include<iostream>
//全局变量,存储在全局/静态存储区
int globalvar = 10;
//常量,通常存储在常量区 不可以修改
const int constvar = 5;
//函数定义,编译后的函数体存储在代码区
void printhello() {
cout << "hello" << endl;
}
int main() {//main函数的编译后机器指令存储在代码区
//局部变量 存储在栈区
int localvar = 20;
printhello();//调用函数
cout << globalvar<< endl;
cout << constvar<< endl;
cout << localvar<< endl;
}
注意事项:
2、全局/静态存储区
全局/静态存储区的特点:
1.生命周期长:变量从程序开始执行时创建,结束时销毁,生命周期贯穿程序始终
2.初始化行为:全局变量和静态变量若没有被初始化则会自动初始化为0
3.内存分配:内存在编译时就已确定,不会在运行时改变
4.作用域与可见性:全局变量定义后在文件外也可以访问,只要在其他文件使用extern关键字声明。
静态变量的作用域限定在它所在的文件或函数中,对于静态全局变量,它阻止了其他文件通过extern访问该变量。
使用方法:
全局变量:在函数外部定义的变量自动成为全局变量,在整个程序都是可见的。
int globalvar = 42;//初始化的全局变量,存放在初始化数据区
在其他文件中访问globalvar
extern int globalvar;
静态全局变量:在全局变量前加上static关键字,可以限制其作用域,使其只能在它的文件中可见。
static int staticglobalvar = 10;//静态全局变量,只在本文件内可见
静态局部变量:在函数内部定义的静态变量,每次调用函数式不会重新创建,保持其值直到下次调用(下次调用忽略初始化语句)
void fun() {
static int staticvar = 0;//静态局部变量,只在fun函数内部可见,且只初始化一次
staticvar++;
cout << staticvar;
}
两次调用fun函数所显示分别为1 2
静态成员变量:属于类的静态成员变量,他们在所有对象间共享,需要在类外进行定义和初始化
class Myclass {
public:
static int staticmembervar;
};
int Myclass::staticmembervar = 10;//静态成员变量的定义和初始化
3、堆区
堆区的特点:
1.动态内存分配:运行时可以根据需要动态分配和释放内存。
2.手动管理:程序员负责分配(new/malloc)和释放(delete/free)内存。
3.无自动销毁机制:内存不会自动释放,必须自行释放。
4.内存大小灵活:可以动态申请任意大小的内存块,只受限于系统的可用内存。
5.存取速度较慢:与栈区相比,堆区存取速度较慢,且频繁进行动态分配和释放,可能会导致内存碎片化
使用方法:
分配内存:使用new分配内存,还能调用构造函数初始化对象
int* ptr = new int;//分配一个int大小的内存
Myclass* obj = new Myclass();//分配并初始化Myclass对象
释放内存:使用delete释放new分配的内存,new[]则对应delete[]来释放
delete ptr;//释放一个int大小的内存
delete obj ;//释放Myclass对象内存
分配数组:可以使用new操作符分配数组,使用delete[]释放数组内存
int* arr = new int[10];
delete[] arr;
注意事项:
5.申请堆区 1块int大小的空间
int* p = new int(5);//new的底层是malloc ()默认初始为0
cout << *p;
delete p;//释放空间
p野指针 指向一块已经释放的空间 野指针没法正常使用
为避免问题产生 需将指针置空
p = NULL;
6.new和malloc的区别
1、new的返回值不需要强转,malloc需要强转
2、new是运算符,malloc是库函数
3、new不需要传入具体的字节个数,malloc需要传入
4、new创建失败会抛出异常,malloc会返回0
5、new创建时先malloc再调用构造函数,删除时,先调用析构函数再free
4、栈区
栈区的特点:
1.自动管理:栈的内存分配和释放是完全自动进行的。函数调用则局部变量和参数自动分配到栈上,函数执行完毕便会自动清理掉。
2.速度快:栈区内存分配和释放由CPU直接支持,因此速度非常快。此外,栈上的数据存储在连续内存地址上,提高缓存效率。
3.空间有限:与堆相比,栈的大小相对较小。取决于操作系统和程序的运行环境,一旦超出就会导致栈溢出,引发程序崩溃。
4.作用域和生命周期:栈上的局部变量只在其定义的函数内部可见,生命周期仅限于函数执行期间。
使用方法:
局部变量定义:在函数内部声明的变量默认分配到栈上
void fun() {
int localvar = 10;//局部变量,存储在栈上
}
函数调用:函数调用信息(包括返回地址和参数)都会被压入栈中,函数返回时会自动清理。
void fun(int a) {
return a;
}
递归:递归函数每次调用都会在栈上创建新的局部变量和参数,深度过大的递归可能导致栈溢出。
5、常量区
常量区的特点:
1.只读:常量区数据初始化后就不允许被修改
2.程序生命周期内持久:数据从开始执行程序就存在,直到程序结束释放
3.共享:可以被程序多个部分共享。
4.内存效率:可以提高内存的使用率,因为相同的常量值不需要在内存中多个地方重复存储。
使用方法:
字符串字面量:字符串字面量自动存储在常量区
const char* str = "hello world!";
const修饰的变量:const关键字声明的变量通常放置在常量区。
const int maxcount = 100;
枚举:枚举类型的值也被视为常量,编译时被分到常量区
enum Color{RED,GREEN,BLUE};