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可自己计算类型的大小,返回对应类型的指针。
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 ); }
最后这个算一个扩展的图,我就是觉得挺有用就放上来了
喜欢编程的新手小白们~ 咱们都是一样的人,我们会在这个公众号下,经常的更新一些知识,大家可以过来讨论和指出我们的不足。
欢迎扫一扫关注我们~~~
相关文章推荐
- C++中的new和delete——读书笔记总结
- c++ new delete知识总结
- c/c++笔试题——C++中 new/delete 概念和用法总结
- 【C++总结】C++的new和delete
- C++中 new/delete 概念和用法总结
- C++复习要点总结之四New和delete使用
- 深入C++ new/delete,malloc/free 总结
- c/c++笔试题——C++中 new/delete 概念和用法总结
- C++中的new与delete总结
- C++中new和delete的实质--代码解释
- c++中new和delete的使用方法
- C++内存管理基础之new & delete
- C++中的delete—— C++中的new之姊妹篇
- [收藏]C++ Tips(2)--new,delete
- malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存
- [收藏]C++ Tips(2)--new,delete
- 关于C++中的new 和 delete
- C++中有了malloc/free,为什么还要用new/delete
- C++中new(delete)和malloc(free)的常见问题
- C++内存管理基础之new & delete