malloc、free与new delete的区别

本文深入对比了C++中new和malloc两种动态内存管理方式的区别,包括用法、功能、安全性及适用场景,并通过实例展示了如何在C++程序中正确使用new和malloc进行内存分配与释放。

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

转载自:http://www.cppblog.com/Lee/archive/2009/03/09/75990.html

相同点:都可用于申请动态内存和释放内存

不同点
(1)操作对象有所不同
malloc与free是C++/C 语言的标准库函数,new/delete 是C++的运算符。对于非内部数据类的对象而言,光用maloc/free 无法满足动态对象的要求。对象在创建的同时要自动执行构造函数, 对象消亡之前要自动执行析构函数。由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加malloc/free。

(2)在用法上也有所不同
函数malloc 的原型如下:
void * malloc(size_t size);
用malloc 申请一块长度为length 的整数类型的内存,程序如下:
int *p = (int *) malloc(sizeof(int) * length);
我们应当把注意力集中在两个要素上:“类型转换”和“sizeof”。

malloc 返回值的类型是void *,所以在调用malloc 时要显式地进行类型转换,将void * 转换成所需要的指针类型。

malloc 函数本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。

函数free 的原型如下:
void free( void * memblock );
为什么free 函数不象malloc 函数那样复杂呢?这是因为指针p 的类型以及它所指的内存的容量事先都是知道的,语句free(p)能正确地释放内存。如果p 是NULL 指针,那么free

对p 无论操作多少次都不会出问题。如果p 不是NULL 指针,那么free 对p连续操作两次就会导致程序运行错误。

new/delete 的使用要点
运算符new 使用起来要比函数malloc 简单得多,例如:
int *p1 = (int *)malloc(sizeof(int) * length);
int *p2 = new int[length];
这是因为new 内置了sizeof、类型转换和类型安全检查功能。对于非内部数据类型的对象而言,new 在创建动态对象的同时完成了初始化工作。如果对象有多个构造函数,那么new 的语句也可以有多种形式。

如果用new 创建对象数组,那么只能使用对象的无参数构造函数。例如
Obj *objects = new Obj[100]; // 创建100 个动态对象
不能写成
Obj *objects = new Obj[100](1);// 创建100 个动态对象的同时赋初值1
在用delete 释放对象数组时,留意不要丢了符号‘[]’。例如
delete []objects; // 正确的用法
delete objects; // 错误的用法
后者相当于delete objects[0],漏掉了另外99 个对象。

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

1  new自动计算需要分配的空间,而malloc需要手工计算字节数
2  new是类型安全的,而malloc不是,比如:
int* p = new float[2]; // 编译时指出错误
int* p = malloc(2*sizeof(float)); // 编译时无法指出错误
new operator 由两步构成,分别是 operator new 和 construct
3  operator new对应于malloc,但operator new可以重载,可以自定义内存分配策略,甚至不做内存分配,甚至分配到非内存设备上。而malloc无能为力
4  new将调用constructor,而malloc不能;delete将调用destructor,而free不能。
5  malloc/free要库文件支持,new/delete则不要。 


1. 本质区别
malloc/free是C/C++语言的标准库函数,new/delete是C++的运算符。
对于用户自定义的对象而言,用maloc/free无法满足动态管理对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。

class Obj
{
public :
      Obj(
) { cout << “Initialization” << endl; }
      
~Obj() { cout << “Destroy” << endl; }
      
void Initialize() { cout << “Initialization” << endl; }
     
void Destroy() { cout << “Destroy” << endl; }
};

void UseMallocFree()
{
      Obj  
*= (obj *) malloc(sizeof( obj ) );    // allocate memory
      a->Initialize();                                                // initialization
      
//
      a->Destroy();                                                // deconstruction
      free(a);                                                           // release memory
}

void UseNewDelete(void)
{
    Obj  
*= new Obj;                                         
    
//
    delete a;
}

类Obj的函数Initialize实现了构造函数的功能,函数Destroy实现了析构函数的功能。函数UseMallocFree中,由于malloc/free不能执行构造函数与析构函数,必须调用成员函数Initialize和Destroy来完成“构造”与“析构”。所以我们不要用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。

2. 联系
既然new/delete的功能完全覆盖了malloc/free,为什么C++还保留malloc/free呢?因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。如果用free释放“new创建的动态对象”,那么该对象因无法执行析构函数而可能导致程序出错。如果用delete释放“malloc申请的动态内存”,理论上讲程序不会出错,但是该程序的可读性很差。所以new/delete,malloc/free必须配对使用。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

<think>首先,用户的问题是:“我想理解在C/C++中动态内存管理时malloc/freenew/delete区别及使用场景 请问C/C++中 malloc freenew 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/freenew/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、付费专栏及课程。

余额充值