个人主页:Lei宝啊
愿所有美好如期而遇
目录
C/C++内存分布
C语言中动态内存管理方式
C++中动态内存管理
operator new与operator delete函数
new和delete的实现原理
定位new表达式(placement-new)
常见面试题
C/C++内存分布
我们先来看一段代码:
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);
}
第一组问题:
- globalVar
- staticGlobalVar
- staticVar
- localVar
- num1
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);
}
- char2 *char2
- pChar3 *pChar
- ptr1 *ptr1
- sizeof(num1)
- sizeof(char2) strlen(char2)
- sizeof(pChar3) strlen(pChar3)
- sizeof(ptr1)
C语言中动态内存管理方式
malloc/calloc/realloc/free
C++中动态内存管理
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
new/delete操作内置类型
operator new与operator delete函数
首先我们要明白operator new和operator delete是函数,而new和delete是操作符,他们直接是有联系,但不是重载关系,只是祖师爷起名字这么起。
在operator new函数里调用了malloc函数,也就是说其实可以将他看做是malloc函数的封装,但是不同的是,malloc函数申请空间失败后返回NULL,而operator new函数里实现了判断malloc申请空间失败就抛出异常。
在operator delete函数里也就是调用了free函数,这个函数主要是为了和operator new函数对称匹配。
new和delete的实现原理
对内置类型来说
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表达式(placement-new)
定位new是在已申请的原始内存空间中掉用一个构造函数初始化一个对象。
这个我们现阶段用不上,毕竟直接创建对象自动调用进行初始化多好,总不能malloc自定义类型的对象,然后使用定位new吧,就像这样:
哪个更好一目了然,我们的定位new真正用途是在内存池那里才会展现。
常见面试题
- malloc和free是函数,而new和delete是操作符
- malloc开辟空间需要计算大小,而new只需要加上类型,如果需要开辟空间,只需要在[]里指定大小即可。
- malloc返回值为void*类型,使用时需要强制转换,而new不需要。
- malloc开辟内存空间失败返回NULL,而new则是抛出异常。
- malloc开辟的内存空间是原始的,不会初始化,也不能初始化,而new开辟的内存空间可以手动初始化,如果是自定义类型,还会自动去调用他的构造函数;而delete在释放内存空间时会先去调用自定义类型对象的析构函数,free不会。