C++ new与malloc和delete及free动态内存管理及区别介绍

 更新时间:2022年12月19日 12:56:37   作者:Huuaaaaa  
这篇文章主要介绍了深入理解C++中的new/delete和malloc/free动态内存管理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一般情况-堆上申请普通变量空间

申请堆空间时,实验表明 new/malloc 与 delete/free 是可以混用的,即可以通过free()释放掉new出来的一块内存。

int main() {
	int *p = new int(123);
	delete p;
	//free(p);
}

特殊情况-堆上申请对象空间

class Person{
public:
	Person(){
		cout << "construct call ......" << endl;
	}
	~Person(){
		cout << "destruct call ......" << endl;
	}
private:
	int m_age;
};
int main() {
	Person *ptr = new Person();
	if (ptr != nullptr)
	{
		free(ptr);
	}
	return 0;
}

单步走看内存分布图:

可以看到,执行完free(ptr) 后,内存确实是被释放了。(补充一下:fd作为开始结束的标志,"cd cd cd cd"代表开辟的内存,四个字节)

但是!对于一个对象而言,new和delete关键字还额外做了 调用构造函数和调用析构函数这两个步骤。

可以看到,程序只调用了构造函数(new关键字产生),但是由于使用的是free(),因此并没有调用类中的析构函数。

一般情况-堆上申请普通数组空间

int main() {
	int *ptr = new int[10];
	delete[]ptr;
	//delete ptr;
	return 0;
}

我们知道,用new在堆上申请数组空间,一般delete的时候都需要加上[ ] ,即 delete[ ] 。

但实验表明,如果不涉及到类对象,不加[ ]也同样可以实现空间的释放,加不加[ ]是没有区别的。

特殊情况-堆上申请对象数组空间

int main() {
	Person *ptr = new Person[10];
	delete ptr;
	return 0;
}

当new一个对象数组时,如果没有用delete[ ] ,会发生崩溃报错:

修改成delete [ ] ptr后,程序正常运行,并调用了十次构造函数和十次析构函数:

进一步探索:为什么修改为delete [ ] 就会调用十次析构函数?它是如何知道创建了十个对象就一定会析构十个对象?

查看一下此种情况下的内存分布:

可以看到我们申请的堆对象数组空间(10个),仔细查看改起始地址的前一个地址,按道理这并不属于我们分配的空间,为什么会多一个地址?

0x011E4EC8 ,该地址保存的值显示为16进制,转换为十进制刚好为10(0a 00 00 00)。这个10代表着什么?

不妨修改一下这个地址,0a 00 00 00 修改成 07 00 00 00 后接着单步走:

此时原来的十个地址空间的确是完整的被释放了,但是析构函数只被调用了 7次!正好是自己修改的那个内存地址的值。

到这里可以得出结论: 编译器是如何记录new 创建出来数组对象的个数, 就是简单的在创建空间的前一个地址,记录了创建对象的个数,析构的时候就按照这个地址的值进行析构。

总结

1. 申请一个堆上的对象时,不允许混搭new/delete 必须搭配使用。

2. new [ ] 和 delete [ ] 一定要配套使用,特别是申请对象数组时。

3. vs编译器会在new [ ] 申请对象数组时,在堆开始的前4个字节写入当前数组的长度,用于记录delete [ ]释放时候的析构函数调用。

到此这篇关于C++ new与malloc和delete及free动态内存管理及区别介绍的文章就介绍到这了,更多相关C++动态内存管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一篇文章带你了解C++Primer学习日记--处理数据

    一篇文章带你了解C++Primer学习日记--处理数据

    今天小编就为大家分享一篇关于C++对数器的使用讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2021-08-08
  • C++报错:Id returned 1exit status的解决办法

    C++报错:Id returned 1exit status的解决办法

    最近刚学c语言,不止一次遇到了同一种报错,经过总结分享给大家,下面这篇文章主要给大家介绍了关于C++报错:Id returned 1exit status的解决办法,需要的朋友可以参考下
    2023-04-04
  • C++ 数据结构之对称矩阵及稀疏矩阵的压缩存储

    C++ 数据结构之对称矩阵及稀疏矩阵的压缩存储

    这篇文章主要介绍了C++ 数据结构之对称矩阵及稀疏矩阵的压缩存储的相关资料,这里实现稀疏矩阵和对称矩阵的压缩存储的实例,需要的朋友可以参考下
    2017-08-08
  • c++命名对象和匿名对象的解析

    c++命名对象和匿名对象的解析

    像按值传递的对象(函数入参,函数返回值)都是匿名对象,那匿名对象的特点是什么呢?下面通过实例代码给大家解析c++命名对象和匿名对象的相关知识,感兴趣的朋友一起看看吧
    2021-10-10
  • 基于C++执行内存memcpy效率测试的分析

    基于C++执行内存memcpy效率测试的分析

    本篇文章对C++中执行内存memcpy的效率进行了分析测试。需要的朋友参考下
    2013-05-05
  • C++设计模式之建造者模式(Builder)

    C++设计模式之建造者模式(Builder)

    这篇文章主要介绍了C++设计模式之建造者模式Builder的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • C语言自动生成enum值和名字映射代码

    C语言自动生成enum值和名字映射代码

    这篇文章主要介绍了C语言自动生成enum值和名字映射代码的相关资料,需要的朋友可以参考下
    2015-12-12
  • C语言简易版flappy bird小游戏

    C语言简易版flappy bird小游戏

    这篇文章主要为大家详细介绍了C语言简易版flappy bird小游戏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • C++实现基于静态数组的顺序表

    C++实现基于静态数组的顺序表

    这篇文章主要介绍了C++实现基于静态数组的顺序表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • 深入了解C语言的动态内存管理

    深入了解C语言的动态内存管理

    所谓动态和静态就是指内存的分配方式。动态内存是指在堆上分配的内存,而静态内存是指在栈上分配的内存,本文将用5600字带你深入了解动态内存管理,感兴趣的可以学习一下
    2022-07-07

最新评论