C++中通过new和delete运算符进行动态内存管理。
int *p1=new int;
int *p2=new int(3);//3将其初始化为3
int *p3=new int[3]//3表示对象个数。
delete p1;
delete p2;
delete [] p3;
malloc/free与new/delete的区别:
·malloc/free是C/C++标准库的函数,而new/delete是C++操作符。
·malloc/free只是进行申请内存的分配,只能动态申请和释放空间,而new/delete除了能够申请空间和释放空间,还会调用构造函数和析构函数进行初始化和清理工作。
·malloc/free需要手动计算申请的大小,new/delete可自己计算类型的大小,返回对应类型的指针。
操作符new:是一个函数。new/delete与new[]/delete[]的实现是通过以下四个函数实现的,同时以下4个函数可以直接开辟空间
void * operator new (size_t size);
void operator delete (void* p);
void * operator new [](size_t size);
void operator delete[] (void* p);
通过查看这4个函数的源码,作出如下总结
1. operator new/operator delete operator new[]/operator delete[] 和 malloc/free用法一样
2. 他们只负责分配空间/释放空间,不会调调对象构造函数/析构函数来初始化/清理对象。
3. 实际operator new和operator delete只是malloc和free的一层封装。
这四个函数是库函数,并不是运算符的重载。
通过调试:发现:
new做了两件事情:1.调用opertor new()函数分配空间。2.调用构造函数初始化对象。
delete做了两件事情:1.调用析构函数清理对象。2.释放空间。
new []:做了两件事情:1.调用operator new[]函数分配空间。2.调用构造函数初始化对象。
delete[]做了两件事情:1.调用析构函数清理对象,2.释放空间。
另外:用delete[]时没有给出次数,那编译器是如何知道,要调用析构函数的次数呢?
在new []中会多出来的4个字节是用来存放要开辟的对象个数的,将空间的的首地址向后偏移。
A p = new A[3]; int d = ((int*)p - 1);
注意:只有当为类的对象(内置类型)开辟空间,并且该类有自定义的析构函数时,才会有多出的4个字节!
3.定位new表达式:
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
new(place_adress)type
new(place_adress)type(initializer-list)
place_adress必须为一个指针,initializar-list是类型的初始化列表。
4.利用malloc和free实现new/delete/new[]/delete[]
class A
{
public:
A(int _a)
:a(_a)
{
cout << "A" << endl;
}
~A()
{
cout << "~A" << endl;
}
private:
int a;
};
int main()
{
//new的实现
A*pa = (A*)malloc(10 * sizeof(A)+4);
*((int*)pa) = 10;//将第一个占用4字节空间赋值为创建对象的个数
A*pStart = (A*)((int*)(pa + 1));// //new操作符返回的地址是开辟的连续空间的向后移4个字节之后的地址
for (int i = 0; i < 10; i++)
{
new(pStart + i)A(1);//利用定位new表达式
}
int n = *(int*)((pStart - 1));
for (int i = 0; i < n; i++)
{
pStart[i].~A();
}
//free((int*)pStart - 1);
operator delete[]((int *)pStart - 1);//调用operator delete[](char *)函数释放内存空间
system("pause");
return 0;
}