您的位置:首页 > 编程语言 > C语言/C++

C++ — new和delete的总结

2017-03-13 20:43 148 查看

C++动态内存管理

C语言用malloc,calloc,relloc和free来进行动态内存管理。但是在C++中就变得不一样了。C++通过new和delete动态管理内存。  new/delete动态管理

对象。  new[]/delete[]动态管理对象数组。



这里提一下,malloc和free,new和delete,new[]和delete[]一定要成对出现。记住重要的事情说三遍。下面的的代码是对他们一点简单的使用:

class Array
{
public :
Array (size_t size = 10)
: _size(size )
, _a(0)
{
cout<<"Array(size_t size)" <<endl;
if (_size > 0)
{
_a = new int[ size];
}
}

~ Array()
{
cout<<"~Array()" <<endl;
if (_a )
{
delete[] _a ;
_a = 0;
_size = 0;
}
}
private :
int*_a ;
size_t   _size ;
};

void Test ()
{
Array* p1 = (Array*) malloc(sizeof (Array));
Array* p2 = new Array;
Array* p3 = new Array(20);
Array* p4 = new Array[10];

free(p1 );
delete p2 ;
delete p3 ;
delete[] p4 ;
}


让我们来看看运行结果:



这个operator delete你不要以为是运算符重载,千万别这样想,接下来我会介绍到。

我们知道C++是兼容C的,C中已经有C库malloc/free等来动态管理内存,但是人们想要更方便的操作符申请空间,不需要强制转化类型,不需要计算需

要的字节数,这时候new和delete操作符出现了,他们使用起来只是一个操作符,方便又使用

malloc/free和new/delete的区别和联系?

1.它们都是动态管理内存的入口。

2.malloc/free是C/C++标准库的函数,new/delete是C++操作符。

3.malloc/free只是动态分配内存空间/释放空间。而new/delete除了分配空间还会调用构造函数和析构函数进行初始化

与清理(清理成员)。

4.malloc/free需要手动计算类型大小且返回值会void*,new/delete可自己计算类型的大小,返回对应类型的指针。


C++的其他内存管理接口(placement版本)

void * operator new (size_t size);

void  operator delete (size_t size);

void * operator new [](size_t size);

void operator delete[] (size_t size);



总结:

1.operator new/operator delete operator new[]/operator delete[] 和 malloc/free用法一样。

2.他们只负责分配空间/释放空间,不会调用对象构造函数/析构函数来初始化/清理对象。

3.实际operator new和operator delete只是malloc和free的一层封装。

new做了两件事:

1.调用operator new分配空间。

2.调用构造函数初始化对象。

delete也做了两件事:

1.调用析构函数清理对象。

2.调用operator delete释放空间。

new
也做了两件事:

1.调用operator new分配空间。

2.调用N次构造函数分别初始化每个对象。

delete
也做了两件事:

1.调用N次析构函数清理对象。

2.调用operator delete释放空间。

接下来我尝试查看一下他们的底层实现:



刚刚我开始调试进入new的内部,我们按F11进入new的内部后发现了operator new函数,然后我们又在operator函数里

发现了malloc,所以说new的底层实现就是malloc,但是new是一个操作符。





我们已经知道了new的内部结构,接下来我们来看看delete内部的结构,F11进入operator delete函数,我们在里面看

到了一个熟悉的身影,那就是_free _dbg这个是什么东西,这个也不是free啊。我们现在调出free的底层实现,我们来

看看这个_free _dbg是什么东西?



我们发现free函数里面,其实参数都传到了这个函数中,也就是它就是用来释放空间,所以所delete的底层

实现也是使用了free~

总结一下,new[]和delete[]其实和new和delete差不多,他们的底层实现都是用到了malloc和free,但是功能

和实用性都高于malloc和free。

还有一个东西,看下面代码。

class A
{
public:
A()
:_num(10)
{
cout << "构造函数调用了" << endl;
}
~A()
{
cout << "析构函数调用了" << endl;
}
private:
int _num;
};
int main()
{
A* i = new A[10];
delete[] i;
system("pause");
return 0;
}


当程序走到new的时候按道理我们会觉得,会为i开辟40个空间,但是结果呢? 来看看



不是应该是40吗?很多人就不明白了?? 为什么是44??  这个在头上多出来的4个字节是干什么用的呢?

这里我简单的说一下,只要涉及有多个类空间的开辟(也就是new  A
),系统需要知道我在释放空间时需要

调用多少次析构函数,这时候会在多开辟出4个空间,放在这段空间的头部,用来存放  调用析构函数时调用的次数!



这个知识点挺偏的,但是却很有意思的~

你可以试试读取ptr前4个字节的内容,看看结果是不是你new
中的N。

最后我们用一张图剖析一下new/delete & new[]/delete[]。



最后我要对这个new和delete进行简单的实现:

class Array
{
public :
Array (size_t size = 10)
: _size(size )
, _a(0)
{
cout<<"Array(size_t size)" <<endl;
if (_size > 0)
{
_a = new int[ size];
}
}

~ Array()
{
cout<<"~Array()" <<endl;
if (_a )
{
delete[] _a ;
_a = 0;
_size = 0;
}
}
private :
int*    _a ;
size_t  _size ;
};

void Test ()
{
// 1.malloc/free + 定位操作符new()/显示调用析构函数,模拟 new和delete 的行为
Array* p1 = (Array*) malloc(sizeof (Array));
new(p1 ) Array(100);

p1->~Array ();
free(p1 );

// 1.malloc/free + 多次调用定位操作符new()/显示调用析构函数,模拟 new[]和delete[] 的行为
Array* p2 = (Array*) malloc(sizeof (Array)*10);
for(int i = 0; i < 10; ++i )
{
new(p2 +i) Array;
}

for(int i = 0; i < 10; ++i )
{
p2[i ].~Array();
}
free(p2 );
}


最后这个算一个扩展的图,我就是觉得挺有用就放上来了



喜欢编程的新手小白们~   咱们都是一样的人,我们会在这个公众号下,经常的更新一些知识,大家可以过来讨论和指出我们的不足。
欢迎扫一扫关注我们~~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: