住房城乡建设网站官网入口,免费建网站软件系统,网站系统 深圳博域通讯,wordpress网站语言包在 C/C 编程中#xff0c;内存管理是一个核心知识点#xff0c;直接影响程序的性能和稳定性。本文将详细介绍 C/C 中的内存分布、动态内存管理方式及相关原理#xff0c;帮助大家系统掌握这部分知识。一、C/C 内存分布程序运行时#xff0c;内存主要分为以下几个区域#…在 C/C 编程中内存管理是一个核心知识点直接影响程序的性能和稳定性。本文将详细介绍 C/C 中的内存分布、动态内存管理方式及相关原理帮助大家系统掌握这部分知识。一、C/C 内存分布程序运行时内存主要分为以下几个区域栈堆栈存储非静态局部变量、函数参数、返回值等栈是向下增长的。内存映射段高效的 I/O 映射方式用于装载共享动态内存库也可用于进程间通信了解即可。堆用于程序运行时动态内存分配堆是向上增长的。数据段存储全局数据和静态数据。代码段存储可执行的代码和只读常量。内存分布示例分析char char2[] abcdchar2数组在栈上abcd 作为字符串常量在代码段初始化时会将字符串内容拷贝到栈上的数组中。char* pChar3 abcd指针pChar3在栈上其指向的字符串常量 abcd 在代码段。int* ptr1 new int[10]指针ptr1在栈上其指向的动态内存空间在堆上。二、C 语言动态内存管理方式C 语言通过malloc、calloc、realloc和free四个函数进行动态内存管理它们的区别和特性如下函数功能描述初始化特性使用方法malloc从堆区开辟指定字节数的连续空间不初始化空间内是随机值void* malloc (size_t size);calloc从堆区开辟 n 个 “指定大小” 的连续空间可看作malloc初始化自动将空间全部初始化为 0void* calloc (size_t num, size_t size);realloc调整已开辟的堆空间大小支持扩容 / 缩容扩容时保留原数据新空间未初始化缩容时截断数据void* realloc (void* ptr, size_t size);注意事项使用realloc调整空间大小时若扩容成功原指针p会被新指针接管无需单独free(p)只需释放新指针即可。例如void Test() { int* p2 (int*)calloc(4, sizeof(int)); int* p3 (int*)realloc(p2, sizeof(int) * 10); // 无需free(p2)只需释放p3 free(p3); }三、C 内存管理方式C 语言的内存管理方式在 C 中仍可使用但 C 新增了new和delete操作符更适合处理自定义类型使用更简洁。1. 操作内置类型申请单个元素空间new 类型释放用delete。申请连续空间new[] 类型释放用delete[]必须匹配使用。支持初始化未指定的元素默认置 0。示例代码void Test() { // 动态申请int空间不初始化 int* p1 new int; // 动态申请int空间初始化为10 int* p2 new int(10); // 动态申请3个int的连续空间不初始化 int* p3 new int[3]; // 动态申请10个int的连续空间全部初始化为0 int* p4 new int[10] {0}; // 前5个初始化后5个默认置0 int* p5 new int[10] {1, 2, 3, 4, 5}; // 释放空间必须匹配 delete p1; delete p2; delete[] p3; delete[] p4; delete[] p5; }2. 操作自定义类型new/delete与malloc/free的核心区别对自定义类型new会调用构造函数初始化delete会调用析构函数清理资源。示例代码class A { public: A(int a1 0, int a2 0) : _a1(a1), _a2(a2) { cout A(): endl; } ~A() { cout ~A(): endl; } private: int _a1, _a2; }; int main() { A* p1 new A(1); // 调用构造函数 A* p2 new A[3]{A(1,1), A(2,2), A(3,3)}; // 调用3次构造函数 delete p1; // 调用析构函数 delete[] p2; // 调用3次析构函数 return 0; }四、operator new 与 operator delete 函数new和delete是操作符底层通过全局函数operator new和operator delete实现内存申请与释放。operator new内部通过malloc申请空间失败时抛异常而非返回 NULL。operator delete内部通过free释放空间。五、new 和 delete 的实现原理1. 内置类型与malloc/free功能类似但new失败时抛异常malloc返回 NULLnew[]/delete[]用于连续空间需匹配使用。2. 自定义类型new的原理调用operator new申请空间在空间上执行构造函数。delete的原理在空间上执行析构函数调用operator delete释放空间。new T[N]的原理调用operator new[]申请 N 个对象的空间执行 N 次构造函数。delete[]的原理执行 N 次析构函数调用operator delete[]释放空间。注意对有析构函数的自定义类型数组delete必须配合[]使用否则会因释放位置错误导致崩溃。示例代码class A { public: A(int a1 0, int a2 0) : _a1(a1) , _a2(a2) { cout A(): endl; } A(const A aa) : _a1(aa._a1) { cout A(const A aa) endl; } ~A() { cout ~A(): endl; } private: int _a1 0; int _a2 0; }; class B { private: int _b1 0; int _b2 0; }; int main() { //int* p1 new int[10]; //free(p1); //内置类型可以这样写,不涉及析构 //B中没有显示写析构函数 //B* p2 new B[10]; //申请10 * 8个字节 //delete p2; //A中显示写析构函数了 A* p3 new A[10]; //申请8 10 * 8个字节前8个字节放的是个数64位系统32位就是410 * 8个字节 //delete p3; //报错因为只释放了一部分,一整段空间不能在中间释放 delete[] p3; // 有析构函数的类释放时要在delete后加上[],实际释放的位置要往前偏移8个字节64位或4个字节32位 return 0; }六、定位 new 表达式placement-new在已分配的原始内存中手动调用构造函数初始化对象格式new (place_address) type(initializer-list)场景配合内存池使用内存池分配的空间未初始化需手动调用构造函数。示例A* p (A*)malloc(sizeof(A)); // 仅开辟空间未初始化 new (p) A(1, 2); // 调用构造函数初始化 p-~A(); // 手动调用析构函数 free(p); // 释放空间七、malloc/free 与 new/delete 的区别malloc/free和new/delete的共同点是都是从堆上申请空间并且需要用户手动释放。不同的地方是1. malloc和free是函数new和delete是操作符2. malloc申请的空间不会初始化new可以初始化3. malloc申请空间时需要手动计算空间大小并传递new只需在其后跟上空间的类型即可 如果是多个对象[]中指定对象个数即可4. malloc的返回值为void*, 在使用时必须强转new不需要因为new后跟的是空间的类型5. malloc申请空间失败时返回的是NULL因此使用时必须判空new不需要但是new需要捕获异常6. 申请自定义类型对象时malloc/free只会开辟空间不会调用构造函数与析构函数而new 在申请空间后会调用构造函数完成对象的初始化delete在释放空间前会调用析构函数完成空间中资源的清理释放