无锡点个赞建站,郑州百度网站快速优化,电子图书馆网站建设,电子商务网站预算C#xff1a;渴望力量吗#xff0c;少年#xff1f; 文章目录 一、C内存管理方式1. new/delete操作内置类型2. new和delete操作自定义类型 二、operator new与operator delete函数三、new和delete的实现原理1. 内置类型2. 自定义类型 四、内存泄漏1. 什么是内存泄漏2. 内存泄… C渴望力量吗少年 文章目录 一、C内存管理方式1. new/delete操作内置类型2. new和delete操作自定义类型 二、operator new与operator delete函数三、new和delete的实现原理1. 内置类型2. 自定义类型 四、内存泄漏1. 什么是内存泄漏2. 内存泄漏的危害3. 堆内存泄漏(Heap leak)4. 解决方案 一、C内存管理方式 C语言内存管理方式在C中可以继续使用但有些地方就无能为力而且使用起来比较麻烦因此C又提出了自己的内存管理方式通过new和delete操作符进行动态内存管理。
1. new/delete操作内置类型
int main()
{// 动态申请一个int类型的空间int* ptr4 new int;// 动态申请一个int类型的空间并初始化为10 int* ptr5 new int(10);// 动态申请10个int类型的空间int* ptr6 new int[3];delete ptr4;delete ptr5; delete[] ptr6;// 额外支持开空间初始化int* p6 new int(10);//注意这里是赋值为10int* p7 new int[10]{1,2,3};//和C语言一样这种情况下没有初始化到的部分默认为0int* p8 new int[10]{};return 0;
}2. new和delete操作自定义类型 在申请自定义类型的空间时new会调用构造函数delete会调用析构函数而malloc与free不会。而他们对内置类型是几乎是一样的。
class A
{
public:A(int a 0): _a(a){cout A(): this endl;}~A(){cout ~A(): this endl;}private:int _a;
};
int main()
{// malloc没有办法很好支持动态申请的自定义对象初始化A* p1 (A*)malloc(sizeof(A));//p1-_a 0;//p1-A(1);// 自定义类型开空间的同时调用构造函数初始化A* p2 new A;A* p3 new A(3);// 自定义类型调用析构函数释放空间delete p2;delete p3;A* p4 new A[10];delete[] p4;/*下面三种写法都是一样的A aa1(1);A aa2(2);A* p5 new A[10]{ aa1, aa2 };delete[] p5;A* p6 new A[10]{ A(1), A(2) };delete[] p6;A* p7 new A[10]{ 1, 2 };delete[] p7;
*/return 0;
}二、operator new与operator delete函数 new和delete是用户进行动态内存申请和释放的操作符operator new 和operator delete是系统提供的全局函数new在底层调用operator new全局函数来申请空间delete在底层通过operator delete全局函数来释放空间。 operator new该函数实际通过malloc来申请空间当malloc申请空间成功时直接返回申请空间失败尝试执行空间不足应对措施如果改应对措施用户设置了则继续申请否则抛异常。
typedef char DataType;
class Stack
{
public:Stack(size_t capacity 4){cout Stack() endl;_array new DataType[capacity];//析构函数对应也得用delete释放空间//_array new char[0x7ffffffffff];//如果取消注释那么对应的第二段代码会抛出异常_capacity capacity;_size 0;}void Push(DataType data){// CheckCapacity();_array[_size] data;_size;}~Stack(){cout ~Stack() endl;delete[] _array;_array nullptr;_size _capacity 0;}
private:// 内置类型DataType* _array;int _capacity;int _size;
};
class A
{
public:A(int a 0):_a1(a){}~A(){cout ~A() endl;}private:int _a1;
};
int main()
{Stack* pst1 (Stack*)operator new(sizeof(Stack));//相当于malloc创造它是为了符合抛出异常的方式operator delete(pst1);//相当于free//其实上面两个函数主要都不是让我们直接使用而是分别封装在new和delete中new就相当于operator new和调用构造函数Stack* pst2 new Stack;delete pst2;//free(pst2);A* p2 new A[10];delete[] p2;return 0;
}new和delete一定要匹配使用否则后果可能是未定义的
三、new和delete的实现原理
1. 内置类型 如果申请的是内置类型的空间new和mallocdelete和free基本类似不同的地方是new / delete申请和释放的是单个元素的空间new[]和delete[]申请的是连续空间而且new在申请空间失败时会抛异常malloc会返回NULL。
2. 自定义类型
1new的原理 a.调用operator new函数申请空间 b.在申请的空间上执行构造函数完成对象的构造 2delete的原理 a.在空间上执行析构函数完成对象中资源的清理工作 b.调用operator delete函数释放对象的空间 3new T[N]的原理 a.调用operator new[]函数在operator new[]中实际调用operator new函数完成N个对象空间的申请 b.在申请的空间上执行N次构造函数 4delete[]的原理 a.在释放的对象空间上执行N次析构函数完成N个对象中资源的清理 b.调用operator delete[]释放空间实际在operator delete[]中调用operator delete来释放空间
四、内存泄漏
1. 什么是内存泄漏 内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失而是应用程序分配某段内存后因为设计错误失去了对该段内存的控制因而造成了内存的浪费。
2. 内存泄漏的危害 长期运行的程序出现内存泄漏影响很大如操作系统、后台服务等等出现内存泄漏会导致响应越来越慢最终卡死。
void MemoryLeaks()
{// 1.内存申请了忘记释放int* p1 (int*)malloc(sizeof(int)); int* p2 new int;// 2.异常安全问题int* p3 new int[10];Func(); // 这里Func函数抛异常导致 delete[] p3未执行p3没被释放. delete[] p3;
}3. 堆内存泄漏(Heap leak) 作为初学者我们更加关注的是这方面的泄露。堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放那么以后这部分空间将无法再被使用就会产生Heap Leak。
4. 解决方案
内存泄漏非常常见一般解决方案分为两种 1事前预防型。如智能指针等 2事后查错型。如泄漏检测工具。