目录
一、C/C++的内存分布
🍔内存的划分
🍟C语言动态内存管理方式
🌮C++动态内存管理方式
二、new 和 delete
🍔new 和 delete 操作自定义类型
🍟operator new 与 operator delete 函数
🌮面试题:new/delete 和 malloc/free的区别
三、结语
一、C/C++的内存分布
🍔内存的划分
🌟请看下面代码中,各种类型是如何分布的?
//全局 int n1 = 0; static int static_n1 = 0;void test_1() {//局部static int static_n2 = 0;int n2 = 0;int num1[10] = { 1 };char C1[] = "abcd";const char* pC2 = "abcd";int* ptr1 = (int*)malloc(sizeof(int) * 4);int* ptr2 = (int*)calloc(4, sizeof(int));int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);free(ptr1);free(ptr3); }
🍟C语言动态内存管理方式
👉简单回顾:
🌟C语言中动态内存管理主要通过:malloc/calloc/realloc/free
void test_2() {int* p1 = (int*)malloc(sizeof(int) * 4);free(p1);int* p2 = (int*)calloc(4, sizeof(int));int* p3 = (int*)realloc(p2, sizeof(int) * 10);free(p3); }
🌮C++动态内存管理方式
📘 C++有了自己的内存管理方式: 通过 new 和 delete 操作符进行动态内存管理
void test_3() {//动态申请一个int类型的空间//int* prt4 = (int*)malloc(sizeof(int));int* ptr4 = new int;//动态申请一个int类型的空间并初始化为10//int* prt5 = (int*)calloc(10, sizeof(int));int* ptr5 = new int(10);//动态申请10个int类型的空间//int* ptr6 = (int*)malloc(sizeof(int) * 10);int* ptr6 = new int[10];delete ptr4;delete ptr5;delete[] ptr6; }
‼️注意:
1️⃣使用 new 和 delete 是需要匹配使用:
👉 new - delete
👉new[ ] - delete[ ]
2️⃣要注意 初始化 new( ) 和 对象个数 new[ ] 的区别
二、new 和 delete
🍔new 和 delete 操作自定义类型
📘通过上面的介绍,C++和C语言对于动态内存的管理似乎只是使用方式上的不同,那为什么要提出new和delete呢?
原因是C++中常常会将一个对象封装起来,例如日期类,个人信息类...
所以C++中 new/delete 和 malloc/free 的最大区别就是对于这样【自定义类型】的特殊处理
C++中 new/delete 对于自定义类型,除了开辟空间还会调用构造函数和析构函数
void test_4() {//日期类class Date{public:Date(){cout << "Date:"<< this << endl;}~Date(){cout << "~Date:"<< this << endl;}private:int _day;int _month;int _year;};Date* pD1 = (Date*)malloc(sizeof(Date));Date* pD2 = new Date;free(pD1);delete pD2; }
‼️注意:
操作自定义类型时 new 会调用构造函数 delete会调用析构函数,而malloc/free不会
🍟operator new 与 operator delete 函数
new 和 delete 是用户进行动态内存申请和释放的操作符
operator new 和 operator delete是系统提供的全局函数
👉new 在底层调用 operator new ,delete 在底层调用 operator delete
查看汇编可以验证://调用如下代码 Complex* cptr = new Complex(1,2);//通过编译器转换为:Complex* cptr;try{void* mem = ::operator new(sizeof(Complex));cptr = static_cast<Complex*>(mem);cptr->Complex::Complex(1,2);}catch(std::bad_alloc){//内存分配失败的时候将不执行构造函数,直接抛出异常}
使用new时,进行了三步操作:
1️⃣调用operator new分配内存
2️⃣编译器对指针做转型
3️⃣调用构造函数
//调用如下代码: Complex* cptr = new Complex(1,2);...//do somethingdelete cptr;//通过编译器转化为:cptr->~Complex();::operator delete(cptr);
使用delete时,进行了两步操作:
1️⃣调用析构函数
2️⃣调用operator delete释放内存
再看operator new 和operator delete 的实现:operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc){void *p;/* malloc (0) is unpredictable; avoid it. */if (sz == 0)//c++标准要求,即使在请求分配0字节内存时,operator new也要返回一个合法指针sz = 1;while (__builtin_expect ((p = malloc (sz)) == 0, false)){new_handler handler = std::get_new_handler ();//分配不成功,找出当前出错处理函数if (! handler)//如果用户没有定义内存分配错误处理函数,直接抛出bad_alloc异常,否则进入错误处理函数_GLIBCXX_THROW_OR_ABORT(bad_alloc());handler ();}return p;} void operator delete(void* ptr) _NOEXCEPT{if (ptr)::free(ptr);}
❗可以发现,operator new 实际上也是通过malloc分配空间,operate delete 最终是通过free来释放空间的
‼️new 在申请空间失败时会抛异常,malloc 会返回 NULL
🌮面试题:new/delete 和 malloc/free的区别
1️⃣malloc/free 是函数,new/delete 是操作符
2️⃣malloc申请的空间不会初始化,new申请时可以初始化
3️⃣malloc在申请时需要手动计算空间大小,new只需跟上类型即可,如果是多个则使用[ ]
4️⃣malloc的返回值是void*,使用时需要强转,new不需要
5️⃣malloc申请空间失败时,返回NULL,使用时需要判空,new不需要,因为new需要捕获异常
6️⃣对于自定义类型,malloc/free只会申请/释放空间,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成资源的清理
三、结语
🫡你的点赞和关注是作者前进的动力!
🌞最后,作者主页有许多有趣的知识,欢迎大家关注作者,作者会持续更新有意思的代码,在有趣的玩意儿中成长!