动态开辟 new_delete & malloc_free

本文详细介绍了内存分配的三种方式:栈上创建、堆上分配及静态存储区分配,并深入探讨了malloc/free与new/delete的不同特点及使用注意事项。

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

内存分配的三种方式:

1、在栈上创建。在执行函数时,函数内局部变量的存储单元在栈上创建,函数执行结束时这些存储单元会自动释放。特点:效率高、分配的容量有限
2、从堆上分配,也称为动态内存分配。程序在运行的时候用malloc或者new申请内存,并且自己利用free或delete释放内存。
3、从静态存储去分配。在编译时就分配好了内存,这块内存在程序的整个运行期间都存在。例如全局变量和静态变量。

#include<iostream>
using namespace std;
//编译时,分配地址
static int a=10;
void main()
{
    int arr;
    char ch;
}

这里写图片描述

malloc_free使用特点

1、malloc原型,void *malloc(size_t size);.注意类型转换 和 sizeof()
2、free原型,void free(void *memblock);
3、需要判断内存耗尽的问题 开辟为NULL

new_delete使用要点

1、new内置了sizeof()、类型转换 和类型安全检测,对于非内部数据类型的对象,new在创建对象时完成了初始化工作
2、new_handle机制,处理异常

malloc_free & new_delete 开辟、释放空间

#include<iostream>
using namespace std;
const int SIZE=10;

void main()
{
    //动态开辟空间
    int *p = (int*)malloc(sizeof(int)*SIZE);
    //判断内存是否耗尽,进行处理
    /*
    if(p == NULL)
    {
        return ;
    }
    */
    if(p==NULL)
    {
        exit(1);
    }
    //malloc初始化
    for(int i=0;i<SIZE;i++)
    {
        p[i]=i+1;
    }
    //释放
    free(p);
    p=NULL;
    //开辟并进行初始化
    char *q = new char(10);
    delete(q);
    q=NULL;
    //通过构造函数初始化
    char *s=new char[10];
    delete[] s;
    s=NULL;
}

C++中new_delete与malloc_free特点

1、malloc与free是标准的库函数,new与delete是c+ +的运算符。他们都可以完成动态内存的开辟和内存的释放
2、malloc与free无法满足对动态对象的要求。对象创建时要调动构造函数、消亡时自动调用析构函数,由于malloc与free是库函数不是运算符,不在编译器的控制范围,不能把构造函数和析构函数强加于构造函数和析构函数
3、new和delete正好能完成动态内存分配和初始化工作的运算符new,以及一个完成清理和释放内存的运算符delete

#include<iostream>
using namespace std;
class Test
{
public:
    Test(int d=0):data(d)
    {
        cout<<"Create Test object"<<endl;
    }
    ~Test()
    {
        cout<<"Free Test object"<<endl;
    }
private:
    int data;
};

void main()
{
    Test *q= new Test(10);
    delete(q);
    q =NULL;
    //1.开辟空间 2.调用构造函数
    Test *s =new Test[10];
    //1、调用析构函数 2.释放空间
    delete[] s;
    s=NULL;

}

这里写图片描述

new_delete与malloc_free实现

new :完成了Initialize() 与 malloc()的作用,即空间开辟和对象创建、初始化
delete:完成了Destroy()与free()的作用,即对象的清除与空间的释放


#include<iostream>
using namespace std;
#include<vld.h>
const int SIZE=10;
class Object
{
public:
    Object(int d=0):data(d)
    {
        cout<<data<<"new_memory"<<endl;
    }

    ~Object()
    {
        cout<<"delete_memeory!"<<endl;
    }
public:
    Initialize(int d)
    {
        data =d;
        cout<<data<<"Initnalize()"<<endl;
    }
    Destroy()
    {
        cout<<"Destory()"<<endl;
    }


private:
    //若直接释放了空间,而没有摧毁对象,则会造成对象的内存泄露
    //char *str; 
    int data;

};

void Use_new_delete()
{
    //要有带默认值的构造函数或者缺省函数  因为数组不能直接初始化
    //Object *s=new Object[10](1);
    /*
    Object *s=new Object[10];
    delete []s;
    */
    Object *q= new Object(10);
    delete q;
}
void Use_malloc_free()
{   
    Object *p=(Object *)malloc(sizeof(Object)*SIZE);
    //构造对象
    p->Initialize(10);
    //摧毁对象
    p->Destroy();
    //释放空间
    free(p);
    p=NULL;

}
void main()
{
    //malloc_free
    Use_malloc_free();
    //new_delete
    Use_new_delete();
}

这里写图片描述

野指针

理解:野指针不是NULL指针,是指向“垃圾”内存的指针。

原因:

1、指针么有被初始化。
char *p = NULL;
char *str=(char *)malloc(100);
2、指针被free或delete后,没有置NULL。
char *str=(char *)malloc(100);
strcpy(p,"hello");
free(p);
if(p != NULL)
//p所指内存被释放,但p所指的地址还没有改变
if(p != NULL)//没有起到作用
{
strcpy(p,"world");//错误
}

3、指针操作超越了变量的作用范围。

&lt;think&gt;嗯,用户想知道C++中的new操作符底层是否调用了malloc函数。首先,我需要回忆一下C++的内存管理机制。记得在C++中,newdelete是用来动态分配和释放内存的操作符,而C语言中则使用mallocfree。根据之前的参考资料,比如引用[1]提到分配器会调用malloc或操作系统函数,引用[2]则明确说new底层用malloc开辟内存,但还会初始化。引用[3]也对比了newmalloc,指出new更安全,会调用构造和析构函数。 所以,首先可以确定的是,new的底层确实会调用malloc来分配内存。但不仅如此,new还会在分配内存后执行对象的构造函数,这是与malloc不同的地方。比如,当使用new创建一个对象时,比如MyClass* obj = new MyClass();,这里new首先会分配足够的内存,这部分通常通过malloc实现,然后调用MyClass的构造函数来初始化这块内存。 接下来需要解释具体的实现机制。operator new函数在C++中负责分配内存,而用户也可以重载这个函数。标准库中的默认operator new通常会调用malloc,但如果分配失败,会抛出bad_alloc异常,而不是返回空指针,这与malloc不同。这部分内容在引用[1]的代码示例中有体现,operator new内部使用malloc,并在失败时抛出异常。 然后要考虑和malloc的区别。虽然new可能调用malloc,但它增加了初始化的步骤,比如构造函数的调用。而malloc仅仅分配内存,不进行任何初始化。此外,new是类型安全的,不需要进行类型转换,而malloc返回的是void*,需要显式转换。异常处理方面,new在失败时抛出异常,而malloc返回NULL,这些区别在引用[3]中都有提到。 最后,可能需要提到一些特殊情况,比如定位new(placement new),它允许在已分配的内存上构造对象,这时候就不会调用malloc,因为内存已经存在。但这种情况属于高级用法,用户可能不需要深入了解,但作为补充说明可以增加回答的全面性。 总结起来,回答的结构应该是先明确回答&ldquo;是的,new底层调用malloc&rdquo;,然后分点详细说明实现机制、与malloc的区别、可能的自定义重载以及异常处理等。同时要引用提供的资料来支持每个观点,确保回答的准确性。&lt;/think&gt;是的,C++ 的 `new` 操作符在底层实现中通常会调用 `malloc` 函数,但其行为比 `malloc` 更复杂。以下是具体分析: --- ### 1. **`new` 操作符的底层实现** - **内存分配**:`new` 操作符的核心功能是通过 `operator new` 函数实现的。在标准库的默认实现中,`operator new` 会调用低级内存分配函数(如 `malloc`)来从堆中获取内存块[^1]。例如: ```cpp void* operator new(size_t size) { if (void* ptr = malloc(size)) { return ptr; } else { throw std::bad_alloc(); } } ``` 这里直接使用 `malloc` 分配内存,并在失败时抛出异常(而 `malloc` 失败返回 `NULL`)[^2]。 - **初始化操作**:`new` 与 `malloc` 的关键区别在于,`new` 不仅分配内存,还会调用对象的构造函数进行初始化[^3]。例如: ```cpp MyClass* obj = new MyClass(); // 1. 调用 operator new 分配内存(可能用 malloc) // 2. 调用 MyClass 的构造函数初始化内存 ``` --- ### 2. **与 `malloc` 的核心区别** | 特性 | `new` | `malloc` | |--------------------|------------------------------------|----------------------------| | **内存分配** | 调用 `operator new`(通常用 `malloc`) | 直接分配原始内存 | | **初始化** | 自动调用构造函数 | 无初始化 | | **类型安全** | 类型安全,无需显式类型转换 | 返回 `void*`,需强制转换 | | **失败处理** | 抛出 `std::bad_alloc` 异常 | 返回 `NULL` | | **内存大小计算** | 自动根据类型计算大小 | 需手动指定字节数 | --- ### 3. **自定义 `operator new`** 用户可通过重载 `operator new` 实现自定义内存分配策略,例如使用内存池: ```cpp void* operator new(size_t size) { // 自定义分配逻辑(例如复用内存块) return custom_alloc(size); } ``` 但即使自定义,最终仍可能间接依赖 `malloc` 或系统级分配函数。 --- ### 4. **异常处理** - `new` 在内存不足时会抛出异常,而 `malloc` 返回 `NULL`。C++ 提供了 `nothrow` 版本来避免异常: ```cpp MyClass* obj = new (std::nothrow) MyClass(); // 失败时返回 nullptr ``` --- ### 总结 `new` 的底层确实依赖 `malloc` 完成内存分配,但它扩展了以下功能: 1. **构造函数的自动调用**(对象初始化); 2. **类型安全的接口**; 3. **异常驱动的错误处理**; 4. **支持自定义分配策略**。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值