个人主页:Lei宝啊
愿所有美好如期而遇
目录
operator new与operator delete函数
我们先来看一段代码:
- int globalVar = 1;
- static int staticGlobalVar = 1;
-
- void Test()
- {
- static int staticVar = 1;
- int localVar = 1;
- int num1[10] = { 1, 2, 3, 4 };
-
- char char2[] = "abcd";
- const char* pChar3 = "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);
- }
第一组问题:
- void Test()
- {
- char char2[] = "abcd";
- const char* pChar3 = "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);
- }
malloc/calloc/realloc/free

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
new/delete操作内置类型

首先我们要明白operator new和operator delete是函数,而new和delete是操作符,他们直接是有联系,但不是重载关系,只是祖师爷起名字这么起。


在operator new函数里调用了malloc函数,也就是说其实可以将他看做是malloc函数的封装,但是不同的是,malloc函数申请空间失败后返回NULL,而operator new函数里实现了判断malloc申请空间失败就抛出异常。
在operator delete函数里也就是调用了free函数,这个函数主要是为了和operator new函数对称匹配。
对内置类型来说
new操作符底层只调用operator new函数,因为内置类型不需要构造函数和析构函数,所以new也不会调用构造函数
delete操作符只调用operator delete函数,同理,他也不会调用析构函数。

对自定义类型来说
new操作符的底层原理是先调用operator new函数,然后调用构造函数
delete操作符底层原理是先调用析构函数,然后调用operator delete函数
- class Stack
- {
- public:
- Stack(int capacity = 4)
- :_capacity(capacity)
- ,_top(0)
- {
- _a = new int[capacity];
- _top++;
-
- cout << "构造" << endl;
- }
-
- ~Stack()
- {
- delete[] _a;
- _a = nullptr;
- _top = _capacity = 0;
-
- cout << "析构" << endl;
- }
-
- private:
- int* _a;
- int _top;
- int _capacity;
-
- };
-
- int main()
- {
-
- Stack* st = new Stack;
- delete st;
-
- return 0;
- }
我们可以查看一下汇编代码来理解。


- int main()
- {
-
- Stack* st2 = new Stack[3];
- delete[] st2;
-
- return 0;
- }
实际上三个对象的空间是一次性全部申请好,然后每个对象都调用构造函数。

析构的时候我们明明没有给delete[]传大小,他是怎么知道要析构三次的呢?
我们调试看一下内存


operator new[]本质上还是调用operator new函数

operator delete[]里面调用的是operater delete

定位new是在已申请的原始内存空间中掉用一个构造函数初始化一个对象。
这个我们现阶段用不上,毕竟直接创建对象自动调用进行初始化多好,总不能malloc自定义类型的对象,然后使用定位new吧,就像这样:

哪个更好一目了然,我们的定位new真正用途是在内存池那里才会展现。