理解delete和free

本文详细对比了C++中delete和C语言中free的功能差异及应用场景,包括如何正确释放动态分配的数组内存,以及释放内存时析构函数的调用情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1、关于delete和free的区别

 

  • 首先,malloc是库函数,而delete是操作符
  • 申请数组时候使用的区别,如int *p=(int*)malloc(100*sizeof(int)),释放内存的时候直接 free(p)即可,而当int *p=new int[100]释放的时候应为delete []p,注意[]的作用说明释放的是一个数组的内存,如果delete p则只是释放的p[0],其余99个int的内存没有释放;这是因为当指明为[]的时候,编译器实际上是做了一个循环来释放这个数组的所有内存。
  • 使用malloc和free来处理动态内存的时候,仅仅是释放了这个对象所占的内存,而不会调用这个对象的析构函数;使用new和delete就可以既释放对象的内存的同时,调用这个对象的析构函数。

共同之处:

都可以释放指针指向的内存(并没有把指针本身干掉)。在free和delete之后,都需要把指向清理内存的指针置为空,即p=NULL,否则指针指向的内存空间虽然释放了,但是指针p的值还是记录的那块地址,该地址对应的内存是垃圾,p就成了“野指针”。同样会使人认为p是个合法的指针,如果程序较长,我们通常在使用一个指针前会检查p!=NULL,这样就起不到作用了。此时如果再释放p指向的空间,编译器就会报错,因为释放一个已经被释放过的空间是不合法的。而将其置为NULL之后再重复释放就不会产生问题,因为delete一个0指针是安全的。

2、实际例子:

首先:显式调用析构函数,

#include <iostream>
#include <crtdbg.h>
using namespace std;

class MyClass
{
public:
	MyClass()
	{
		n_ = 1;
		cout << "Constructors" << endl;
	}
	~MyClass()
	{
		cout << "Destructors" << endl;
	}
	void display()
	{
		cout << n_ << endl;
	}
private:
	int n_;
};

int main (void)
{
	MyClass *pMyClass = new MyClass;
	pMyClass->~MyClass();
	delete pMyClass;
	
	_CrtDumpMemoryLeaks();
	return 0;
}
输出结果:


说明:delete的时候做了两件事:一是:调用析造函数,二是:调用free释放内存(实际上是调用operator delete)。

其次,若再次调用delete,这个时候程序可以顺利运行,但是运行时报错,说明delete时候释放了内存,但是并没有把指针本身干掉:

当然这个例子比较简单,但是怎样才能防止一个对象没有被重复delete呢?试着将指针置为0,代码和截图如下:

delete一个0指针是没有问题的。

3、总结:

在这里关于指针和动态申请的内存空间总结如下:

1.      指针消亡了,并不表示它指示的动态内存会自动释放;

2.      动态内存释放掉了,如果这个内存是一个动态对象,则并不表示一定会调用这个对象的析构函数;

动态内存释放掉了,并且调用了析构函数,并不表示指针会消亡或者自动变成了NULL。

参考链接:

http://blog.youkuaiyun.com/gukesdo/article/details/7506155

http://blog.youkuaiyun.com/jnu_simba/article/details/8803377







<think>首先,用户的问题是:“我想理解在C/C++中动态内存管理时malloc/freenew/delete的区别及使用场景 请问C/C++中 malloc free new delete 的使用区别及适用场景”。我需要基于提供的引用系统指令来回答。 系统指令包括: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$并单独成段。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 参考的引用: - [^1]: 主要区别:new/delete调用构造函数/析构函数,malloc/free不调用;new自动计算大小,返回正确类型指针,malloc需要手动计算类型转换。 - [^2]: new分配在自由存储区,可能是在堆上;malloc分配在堆上;new/delete可重载,malloc/free不可重载。 - [^3]: 对于内置类型,new不初始化;示例代码。 - [^4]: 表格总结区别:new/delete属于C++,调用构造/析构,返回对象指针,失败抛异常;malloc/free属于C,不调用构造/析构,返回void*,失败返回NULL。 我的回答需要结构化: 1. **介绍动态内存管理**:简要解释为什么需要动态内存管理。 2. **区别对比**:详细对比malloc/freenew/delete。 3. **使用场景**:讨论各自的适用场景。 4. **生成相关问题**:在末尾添加相关问题。 使用中文回答,并确保语法正确。 逐步构建回答: - **步骤1: 介绍**:动态内存管理允许在运行时分配释放内存,用于处理大小未知的数据。 - **步骤2: 区别对比**: - **语法功能**:malloc/free是C库函数;new/delete是C++运算符。 - **构造析构**:new调用构造函数,delete调用析构函数;malloc/free只处理内存分配/释放。 - **类型安全**:new返回正确类型指针;malloc返回void*需要强制转换。 - **内存区域**:new分配在自由存储区(可能堆);malloc分配在堆。 - **失败处理**:new失败抛异常;malloc失败返回NULL。 - **可重载性**:new/delete可重载;malloc/free不可。 - **初始化**:new可以初始化对象;malloc只分配内存。 - **步骤3: 使用场景**: - 在C++中,优先使用new/delete,因为它支持面向对象特性。 - 在C中,只能使用malloc/free。 - 当需要与C代码交互时,可能使用malloc/free。 - 对于非对象类型(如原始内存),malloc/free可能更简单。 - **步骤4: 生成相关问题**:基于主题,添加3-4个相关问题。 在回答中,自然地添加引用标识。例如,当提到区别时,引用[^1]或[^4]。 确保行内数学表达式用$...$,但这里可能不需要数学表达式,除非涉及计算。用户问题没有数学内容,所以可能不需要。 独立公式:如果有公式,用$$...$$,但这里可能不需要。 最后,生成相关问题:例如: 1. new/delete如何实现构造析构函数的调用? 2. 在C++中,如何重载newdelete运算符? 3. malloc/free在C++中有什么风险? 4. 动态内存管理的内存泄漏如何避免?</think>### C/C++中malloc/free与new/delete的区别及使用场景 在C/C++中,动态内存管理是程序运行时分配释放内存的关键机制。`malloc/free`是C语言的标准库函数,而`new/delete`是C++引入的运算符。它们的主要区别在于类型安全、对象生命周期管理内存区域等方面。以下我将逐步解释它们的区别,并讨论适用场景,确保回答基于可靠的技术细节[^1][^4]。 #### 1. **主要区别对比** - **语法功能**: - `malloc/free`:是C标准库函数,`malloc`用于分配内存,`free`用于释放内存。它们只处理原始内存块,不涉及对象初始化或清理。例如: ```c int* p = (int*)malloc(sizeof(int)); // 手动计算大小并强制类型转换 free(p); // 仅释放内存 ``` `malloc`返回`void*`,需手动转换为目标类型[^1][^4]。 - `new/delete`:是C++运算符,`new`分配内存并调用构造函数初始化对象,`delete`释放内存并调用析构函数清理资源。例如: ```cpp int* p = new int; // 自动计算大小,返回int*指针 delete p; // 调用析构函数(如果适用) ``` 对于数组,需使用`new[]``delete[]`[^1][^3]。 - **对象生命周期管理**: - `new/delete`:在分配时调用构造函数(如类对象的初始化),在释放时调用析构函数(如释放成员资源)。这确保了对象的完整生命周期管理[^1][^4]。 - `malloc/free`:仅分配释放原始内存,不调用任何构造函数或析构函数。如果用于对象,可能导致资源泄漏(如未释放内部指针)[^3][^4]。 - **类型安全错误处理**: - `new`:返回目标类型的指针(如`int*`),类型安全;失败时抛出`std::bad_alloc`异常。 - `malloc`:返回`void*`,需强制类型转换,易出错;失败时返回`NULL`[^1][^4]。 - **内存区域**: - `malloc/free`:分配在操作系统的**堆(Heap)**上,是C语言的标准内存池。 - `new/delete`:分配在C++的**自由存储区(Free Store)**,可能位于堆上,但具体位置取决于编译器实现(可重载`new`运算符以改变位置)[^2][^4]。 - **可重载性**: - `new/delete`:可重载运算符,允许自定义内存分配策略(如使用静态存储区)。 - `malloc/free`:不可重载,是固定库函数[^2]。 #### 2. **适用场景** - **优先使用`new/delete`的场景**: - 在C++代码中操作对象(类或结构体),因为它自动处理构造析构,避免内存泄漏。例如: ```cpp class MyClass { public: MyClass() { /* 构造函数 */ } ~MyClass() { /* 析构函数 */ } }; MyClass* obj = new MyClass(); // 调用构造函数 delete obj; // 调用析构函数 ``` - 需要类型安全异常处理的场景,如大型应用开发[^1][^4]。 - 使用C++特性(如继承或多态)时,`delete`能正确调用派生类析构函数。 - **优先使用`malloc/free`的场景**: - 在纯C代码中,或与C库交互时(如调用C函数返回的内存指针)。 - 分配原始内存(如字节数组),不涉及对象初始化。例如: ```c char* buffer = (char*)malloc(1024); // 分配1KB缓冲区 free(buffer); ``` - 性能敏感场景,`malloc/free`开销略低(但差异通常微小)[^3][^4]。 - **混合使用的风险**: - 不可混用:`malloc`分配的内存不能用`delete`释放,反之亦然,否则导致未定义行为(如内存损坏)。C++中,应始终匹配使用:`new`配`delete`,`malloc`配`free`[^1][^3]。 #### 3. **总结建议** - 在C++中,**始终优先使用`new/delete`**,因为它提供完整的对象管理、类型安全异常机制,符合面向对象原则[^1][^4]。 - 仅在遗留C代码或特定性能优化时使用`malloc/free`,并确保手动处理初始化清理。 - 避免常见错误:如用`free`释放`new`分配的对象(忽略析构函数),或忘记数组语法(`delete[]` vs `delete`)[^3]。 通过理解这些区别,您可以更安全地管理动态内存,减少泄漏错误。如果您有具体代码示例,我可以进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值