众所周知,C可以说是C++的一个子集吧!C中也包含动态内存管理,C中动态内存管理,离不开malloc和free函数,而C++动态内存管理,即继承了C的动态内存管理,又有自己的创新。而这创新便是new和delete操作符的出现。
既然有创新,那必然意味着有所不同。其所不同主要有三点:其一不同便是:new,delete是操作符,而malloc和free是函数。其二便是malloc/free只是动态分配内存空间/释放空间。而new/delete除了分配空间/释放空间还会调用构造函数/析构函数进行初始化/清理。其三不同是malloc需要手动计算类型大小且返回值是void* ,new可以自动计算类型的大小,返回对应类型的指针。
在C++中存在着类似malloc和free的函数如下:
其实operator new/operator delete只负责分配空间和释放空间,并不会调用对象的构造函数和析构函数来初始化/处理对象。
new->调用operator new开辟空间->使用构造函数初始化->
delete->使用析构函数处理对象->调用operator delete释放空间->
注:当new所针对的对象为内置类型时,则不会调用构造函数和析够函数
如下图所示,便是new,delete对于不同对象所对应的不同的处理。
将new和delete应用于自定义类型且创建的为非数组变量。
在使用new的时候会将创建的变量的大小以参数的形式传递给operator new函数,而operator new函数又调用maolloc函数来开辟空间,operator new的返回值保存到寄存器中,并且调用构造函数来初始化该返回值所对应的那块空间。完成之后,将寄存器中的内容复制给pa。...在对象空间被销毁之前,调用析构函数处理问题,而所谓的问题便有可能是处理该类中成员变量采用new申请的空间。
随后便是调用operator delete函数去释放A类对象所在的空间!
下图是使用new[]和delete[]创建自定义类型的数组
关于C++动态内存的最后一点便是定位New的使用。
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
如下,是使用定位New和构造函数及析构函数来模拟new和delete操作符。
class A
{
private:
int _a;
int* _ptr;
public:
A(int a=1)
:_a(a)
, _ptr(NULL)
{
cout << "A()" << endl;
_ptr = new int(3);
}
~A()
{
cout << "~A()" << endl;
delete _ptr;
}
};
void test()
{
A* pa = (A *)operator new(sizeof(A));
new(pa)A(5);
(*pa).~A();
operator delete(pa);
//free(pa); 使用free和使用operator delete效果一样
}
int main()
{
test();
system("pause");
return 0;
}
如下,是使用定位New和构造函数及析构函数来模拟new[]和delete[]操作符。
class A
{
private:
int _a;
int* _ptr;
public:
A(int a=1)
:_a(a)
, _ptr(NULL)
{
cout << "A()" << endl;
_ptr = new int(3);
}
~A()
{
cout << "~A()" << endl;
delete _ptr;
}
};
void test()
{
int i = 0;
A* pa = (A *)operator new(sizeof(A)* 5+4);
(*(int *)pa) = 5;
pa = (A*)((int *)pa + 1);
for (i = 0; i < *((int*)pa-1); i++)
{
new(pa + i)A;//调用构造函数
}
for (i = 0; i < *((int*)pa - 1); i++)
{
(pa+i)->~A();
}
operator delete((int *)pa-1);
}
int main()
{
test();
system("pause");
return 0;
}