1、C++的内存分布
1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。
2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存,做进程间通信。
3. 堆用于程序运行时动态内存分配,堆是可以上增长的。
4. 数据段--存储全局数据和静态数据。
5. 代码段--可执行的代码/只读常量
2、内存空间的申请以及释放
C语言的申请:
#include<iostream>
using namespace std;
int main()
{
int *pa = (int*)malloc(sizeof(int));
int * pb = (int*)calloc(10,sizeof(int));//初始化为0
int* pc = (int*)realloc(pb,sizeof(int)*10);//扩展内存
free(pa);
free(pc);
return 0;
}
c++空间的申请
// new 和delete
//new 和delete总是成对出现,数组就带[],非数组就不带[]
class A {
public:
A(int a=0)
:_a(a)
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
int main()
{
int* a = new int; //new一个对象出来,存放在堆上,不做初始化
delete a; //删除一个对象
int* aa = new int[10]; //new一个数组出来,存放在堆上,不做初始化
delete[] aa; //删除
int* b = new int(10); //初始化对象为10
delete b; //删除
int* bb = new int[10]{ 1, 2, 3 }; //初始化前3个,后面被初始化称为0
delete[] bb;
//malloc出来的对象不会调用构造和析构函数
A* Aa = (A*)malloc(sizeof(A));
free(Aa);
//new一个自定义类型的对象出来
//new 对象会自动调用构造和析构函数,对对象进行初始化
A* Aaa = new A;
delete Aaa;
//千万注意,delete 和new配对,delete[]和new[]配对使用
A* c = new A[10];
delete[] c;
return 0;
}
new和delete的底层实现:
其实new和delete靠的是operator new 和 operator delete
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是 系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过 operator delete全局函数来释放空间。operator new 实际也是通过malloc来申请空间,如果 malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施 就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。
3、定位new的实现
定位new的表达式是在已经申请的内存空间上调用构造函数进行初始化
格式 new(place_address(必须是个指针))class_type(init_list)
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
A* p1 = new A;
delete p1;
//A* p2 = new A[3];
//delete[] p2;
A* p3 = (A*)malloc(sizeof(A));
if (p3 == nullptr)
{
perror("malloc");
exit(-1);
}
//定位new,可以显示的调用构造函数---对p3显式调用构造函数-->在STL使用
new(p3)A(1);
//析构函数可以显式调用
p3->~A();
free(p3); //delete p3效果一样
return 0;
}
4、malloc free 以及new delete之间的区别
这两者之间的区别:
1、malloc以及free是函数,而new delete是关键字;
2、对于自定义类型数据,malloc只是申请空间,而new会调用构造函数进行初始化,free和delete同理;
3、malloc 的返回类型是void(*)需要强制类型转换,而new后面直接跟类型;
4、malloc申请失败会返回NULL,而free会抛出异常;
5、malloc申请空间需要手动计算字节数的大小,而new则不需要;
6、申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new 在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。
5、内存泄漏
什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内 存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对 该段内存的控制,因而造成了内存的浪费。 内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。