内存空间
每个应用都有自己独立的内存空间,其内存空间一般都有以下几大区域
-
1.代码段(代码区):用于存放代码
- 2.数据段(全局区) :用于存放全局变量等
- 3.栈空间
每调用一个函数就会给它分配一段连续的栈空间,等函数调用完毕后会自动回收这段栈空间
自动分配和回收
- 4.堆空间:需要主动去申请和释放
堆空间
在程序运行过程,为了能够自由控制内存的生命周期、大小,会经常使用堆空间的内存
堆空间的申请\释放
malloc \ free new \ delete
new [] \ delete []
注意
申请堆空间成功后,会返回那一段内存空间的地址
申请和释放必须是1对1的关系,不然可能会存在内存泄露
现在的很多高级编程语言不需要开发人员去管理内存(比如Java),屏蔽了很多内存细节,利弊同时存在
-
利:提高开发效率,避免内存使用不当或泄露
-
弊:不利于开发人员了解本质,永远停留在API调用和表层语法糖,对性能优化无从下手
堆空间的初始化
// 申请4个字节的堆空间内存
int *p = (int*)malloc(4);
/*char *p = (char *)malloc(4);
*p = 1;
*(p + 1) = 2;
p[0] = 1;
p[1] = 2;*/
void test4() {
int *p = new int; // 内存泄露
p = new int;
delete p;
}
void test5() {
int size = sizeof(int);
int *p = (int *)malloc(size);
// memory set
// 从p开始的4个字节, 每个字节都存放0
memset(p, 0, size);
cout << *p << endl;
free(p);
}
new关键字
void test6() {
// 没有初始化
int *p1 = new int;
// 初始化为0
int *p2 = new int();
// 初始化为5
int *p3 = new int(5);
// 没有初始化
int *p4 = new int[3];
// 全部元素初始化为0
int *p5 = new int[3]();
// 全部元素初始化为0
int *p6 = new int[3]{};
// 首元素初始化为5,其他元素初始化为0
int *p7 = new int[3]{ 5 };
cout << p7[0] << endl;
cout << p7[1] << endl;
cout << p7[2] << endl;
}
memset关键字
memset函数是将较大的数据结构(比如对象、数组等)内存清零的比较快的方法
int size = sizeof(int);
int *p = (int *)malloc(size);
// memory set
// 从p开始的4个字节, 每个字节都存放0
memset(p, 0, size);
cout << *p << endl;
free(p);
Person person;
person.m_id = 1;
person.m_age = 21;
person.m_height = 190;
memset(&person, 0, sizeof(person));
// persons[]数组
Person persons[] = { {1,20,188},{2,23,188},{3,22,180}};
memset(persons, 0, sizeof(persons));
对象的内存
对象的内存可以存在于3种地方
- 1.全局区(数据段):全局变量
- 2.栈空间:函数里面的局部变量
- 3.堆空间:动态申请内存(malloc、new等)
struct Person {
int m_age;
};
// 全局区
Person g_person;
int main() {
// 栈空间
Person person;
// 堆空间
Person *p = new Person();
p->m_age = 20;
}