博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
new、delete和malloc、free详解与混用问题
阅读量:3957 次
发布时间:2019-05-24

本文共 2595 字,大约阅读时间需要 8 分钟。

如有错漏,还望指摘!

以前看到的资料都说,new和delete、new[]和delete[]、malloc和free,必须配套使用,不应该混用。

然而我最近遇到一些相关的问题,因此不得不探究一下,混用了会怎么样呢
其实要想知道能不能混用,问题在于:他们有什么区别
其实很简单:

  1. malloc只负责分配内存,free只负责释放内存。
  2. new在分配内存的同时,还会调用构造函数;delete在释放内存的同时还会调用析构函数。
  3. new[]在分配对应大小内存的同时,还会调用对应次数的构造函数;delete[]同理。

但是这里其实有一个问题:

delete[]是如何知道到底需要调用多少次析构函数的呢?
原来,new[]在分配时,如果类中显式定义了析构函数,new会在分配的时候,根据系统的位数额外分配对应的空间(32位系统分配32位空间,也就是4字节,64位系统分配64位空间,也就是8字节)。如对于32位系统,new[2]分配的空间应该如下:
new[]地址分配示意图
在返回的指针之前,还有一个4字节的header,其中存储了分配的个数,如这里就应该是2。

所以我们很容易就能得出结论:

  1. 对于基本类型而言,没有区别。根据需要new和malloc可以混用,new[]和malloc可以混用,delete、delete[]和free可以混用。
  2. 对于构造函数没有作用的类,new和malloc可以混用。
  3. 对于构造函数有作用的类,如果想混用,需要显式调用构造函数的逻辑实现。
  4. 对于没有显式定义析构函数的类,delete、delete[]和free可以混用。
  5. 对于显式定义析构函数的类,delete[]和new[]必须配套使用,delete和free如果想混用,free需要显式调用析构函数。

代码:

//构造函数和析构函数都没有作用。可以随意混用。class test1{
public: test1(){
}}int main(void){
/* 这里用任意方式分配的内存都可以用任意方式释放 */ //test1 *ptr = new test1; test1 *ptr = new test1[3]; //test1 *ptr = (test1*)malloc(sizeof(test1)); //delete ptr; //delete[] ptr; free(ptr);}
//构造函数有作用。//没有显示定义析构函数,因此delete、delete[]、free可以混用class test2{
public: test2(){
init(); } inline void init(){
cout << "constructor" << endl; }}int main(void){
//test2 *ptr = new test2; //test2 *ptr = new test2[3]; /* 这里如果想用malloc,必须显示调用构造函数的逻辑。 注:由于构造函数无法被显式调用,因此必须另写一个其实现逻辑,也就是这里的init()函数。 */ test2 *ptr = (test2*)malloc(sizeof(test2)); ptr->init(); //delete ptr; delete[] ptr; //free(ptr);}
//构造函数没有有作用。new、new[]、malloc可以混用//显示定义析构函数class test3{
public: test3(){
} ~test3(){
cout << "destructor" << endl; }}int main(void){
//test3 *ptr = new test3; test3 *ptr = (test3*)malloc(sizeof(test3)); //delete ptr; /* 必须显示调用析构函数 */ ptr->~test3(); free(ptr); /* 只要定义了析构函数,即使析构函数内是空的,delete[]和new[]也必须配套使用,否则会一直调用析构函数 */ //test3 *ptr = new test3[3]; //delete[] ptr;}
//对于32位系统,new[]和delete[]的非配套使用。//显示定义析构函数class test3{
public: test3(){
} ~test3(){
cout << "destructor" << endl; }}int main(void){
int n = 3; /* new[]和free混用 */ test3 *ptr1 = new test3[n]; //模拟delete[] for(int i = 0; i < n; i++){
(ptr1 + i)->~test3(); } ptr = (test3*)( ((char*)ptr) - 4 ); free(ptr); /* malloc和delete[] */ //模拟new[] test3* ptr2 = (test3*)malloc(4 + n * sizeof(test3)); //如果是64位系统,这里4换成8 int32_t* temp = (int32_t*)ptr2; //如果是64位系统,这里是int64_t *temp = n; temp++; ptr2 = (test3*)temp; for(int i = 0; i < n; i++){
(ptr2 + i)->init(); } delete[] ptr2;}

转载地址:http://pxxzi.baihongyu.com/

你可能感兴趣的文章
关于dom4j无法解析xmlns问题及生成非UTF-8字符集乱码问题的解决
查看>>
很好的一篇文章 如果让我重做一次研究生 王汎森
查看>>
保护U盘批处理文件
查看>>
hibernate 自动导入sql 文件import.sql 国际化编码的问题的解决方案
查看>>
第七颗头骨 & 忘魂花 凤凰
查看>>
李小龙哲学之言
查看>>
潜伏中体现的潜规则
查看>>
[Java] Appfuse 源代码分析
查看>>
[Java] Appfuse 最佳实践
查看>>
[心情] 如果有一天
查看>>
[随笔] 6月近况小记 & 一个站点优化问题
查看>>
[Perl] 关于 Bugzilla 的一些问题与研究
查看>>
[Linux] 常用 linux 系统命令及维护备忘
查看>>
[Linux] 关于 Ext4 HowTo
查看>>
[杂记] 新年物语&关于Mysql引擎性能测试
查看>>
[心得] 近期更新&关于Infobright
查看>>
[杂记] 流量统计 & 短信接口
查看>>
[Java] JRebel + Maven + Jetty 热部署
查看>>
[算法] 从 Memcached 分布式应用看一致性哈希散列函数的选择
查看>>
[中间件] 消息处理利器 ActiveMQ 的介绍 & Stomp 协议的使用
查看>>