理解delete和free

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


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++中new/delete与malloc/free区别的问题。首先,我得回忆一下之前学过的相关知识,并结合提供的引用内容来整理答案。用户已经给出四个引用资料,我需要仔细理解这些内容,确保回答准确。 首先,用户的问题是关于new/freemalloc/delete之间的区别。不过,根据常规用法,正确的配对是new/deletemalloc/free。可能用户在这里有点混淆,需要明确指出正确的配对方式,并解释为什么不能混用。比如,用new分配的内存应该用delete释放,而malloc分配的内存用free释放,否则可能导致问题。 接下来,根据引用资料,我需要整理出主要的区别点。引用[1]引用[2]都提到了几个关键点:比如malloc/free是函数,而new/delete是操作符;malloc不初始化内存,new会调用构造函数;返回类型计算大小方面的差异;以及失败时的处理方式不同(返回NULL vs 抛出异常)等。引用[4]还提到了newdelete在底层可能调用mallocfree,但会处理构造函数析构函数。 我需要将这些点分门别类,结构清晰地呈现出来。比如可以分为操作符与函数、内存初始化、类型安全、失败处理、构造析构函数的调用等方面。同时,要注意用户提到的混用情况,比如用free释放new出来的内存或用delete释放malloc分配的内存是否可行,这样会有什么后果。 另外,用户提供的示例中引用了多个资料,我需要正确标注引用来源,比如在提到构造析构函数时引用[1]、[2]、[4],在提到类型大小计算时引用[2],等等。引用标识要自然地加在相关段落的末尾,避免干扰阅读。 可能还需要举一些例子,比如代码片段,说明正确的使用方式,以及混用时的问题。例如,用malloc分配一个对象,然后尝试用delete释放,这样不会调用析构函数,可能导致资源泄漏。或者用new分配数组,用free释放,导致未调用析构函数等问题。 另外,用户的问题中可能存在一个误区,即new/freemalloc/delete的组合是否存在。需要明确指出正确的配对,并解释混用的风险。比如,new应该与delete搭配,malloc与free搭配,否则可能导致未定义行为。 还需要考虑回答的结构是否清晰,按照逻辑顺序分点说明,每个点用标题或编号突出,便于用户理解。同时,在回答最后生成相关问题,帮助用户进一步学习,比如关于内存管理的最佳实践,或者如何避免内存泄漏等。 最后,确保使用中文回答,数学公式代码块格式正确。例如,如果有涉及内存大小的计算,可能需要使用行内公式,如$sizeof(int)$,但根据用户提供的示例,可能不需要太多数学公式,重点在代码文字描述。 总结步骤: 1. 确定用户的问题核心,纠正可能的误区(new/delete vs malloc/free的正确配对)。 2. 根据引用资料整理主要区别点,分点详细说明。 3. 加入代码示例说明正确错误用法。 4. 标注引用来源,确保每个引用标识对应正确的内容。 5. 生成相关问题,促进深入学习。</think>### C++中new/delete与malloc/free的区别 在C++中,`new/delete``malloc/free`是两套不同的内存管理机制,它们的核心差异体现在**功能定位**、**类型安全****对象生命周期管理**上。以下是主要区别: --- #### 1. **操作符 vs 函数** - **`new/delete`** 是C++的**操作符**,由编译器直接支持[^2]。 - **`malloc/free`** 是C/C++标准库提供的**函数**,需要包含头文件`<cstdlib>`[^1][^2]。 --- #### 2. **内存分配与初始化** - **`malloc`** 仅分配指定大小的内存,**不调用构造函数**,返回`void*`需手动类型转换[^1][^2]。 ```cpp int* p = (int*)malloc(sizeof(int)); // 未初始化 ``` - **`new`** 分配内存后**自动调用构造函数**,返回类型正确的指针[^1][^4]。 ```cpp int* p = new int(10); // 初始化为10 ``` --- #### 3. **类型安全与大小计算** - **`malloc`** 需手动计算内存大小(如`sizeof(int)*10`),容易出错。 - **`new`** 自动计算类型大小,支持数组分配[^4]。 ```cpp int* arr = new int[10]; // 自动计算总大小 ``` --- #### 4. **错误处理** - **`malloc`** 失败返回`NULL`,需显式检查[^2]。 - **`new`** 失败抛出`std::bad_alloc`异常,可通过`nothrow`版避免异常[^2]。 ```cpp int* p = new (std::nothrow) int[100]; // 失败返回nullptr ``` --- #### 5. **对象生命周期管理** - **`new/delete`** 管理**对象生命周期**: - `new`调用构造函数完成初始化[^4]。 - `delete`调用析构函数释放资源[^1][^4]。 ```cpp class MyClass {...}; MyClass* obj = new MyClass(); // 调用构造函数 delete obj; // 调用析构函数 ``` - **`malloc/free`** 仅操作内存,不涉及对象构造/析构[^1][^4]。 ```cpp MyClass* obj = (MyClass*)malloc(sizeof(MyClass)); // 未构造对象 free(obj); // 未调用析构函数,可能导致资源泄漏 ``` --- #### 6. **混用的风险** - **`new`分配 + `free`释放**: 不会调用析构函数,导致对象资源(如动态内存、文件句柄)泄漏[^4]。 - **`malloc`分配 + `delete`释放**: 可能触发未定义行为,因`delete`期望调用析构函数,但对象未正确构造[^4]。 --- #### 7. **底层实现关联** - `new`的底层可能调用`malloc`,但会封装异常处理构造函数调用[^4]。 - `delete`的底层可能调用`free`,但会先调用析构函数[^4]。 --- ### 总结对比表 | 特性 | `new/delete` | `malloc/free` | |---------------------|----------------------------------|-----------------------------| | 类型 | 操作符 | 函数 | | 初始化/清理 | 调用构造/析构函数 | 仅分配/释放内存 | | 类型安全 | 自动计算大小,返回类型正确指针 | 需手动计算大小,返回`void*` | | 错误处理 | 抛异常(默认) | 返回`NULL` | | 自定义类型支持 | 完整对象生命周期管理 | 仅内存操作 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值