【C++学习】malloc/free与new/delete

【C++学习】malloc/freenew/delete

参考1

参考2

operator new 和 operator delete

mallocfree是 C++/C 语言的标准库函数,new/delete 是 C++的运算符。它们都可用于申请动态内存和释放内存。

内存区域

C++中针对于非内部数据类型的对象,对象每次在创建时需要自动执行构造函数,对象在消亡之前要自动执行析构函数,光用 maloc/free 无法满足动态对象的要求。因此 C++语言需要一个能完成动态内存分配和初始化工作的运算符 new,以及一个 能完成清理与释放内存工作的运算符 delete。注意 new/delete 不是库函数

class Obj 
{ 
public : 
    Obj(void){ cout << “Initialization” << endl; } //构造函数
    ~Obj(void){ cout << “Destroy” << endl; } //析构函数
    void Initialize(void){ cout << “Initialization” << endl; } //模拟构造函数
    void Destroy(void){ cout << “Destroy” << endl; } //模拟析构函数
};

void UseMallocFree(void) 
{ 
    Obj *a = (obj *)malloc(sizeof(obj)); // 申请动态内存 
    a->Initialize(); // 初始化 
    //… 
    a->Destroy(); // 清除工作 
    free(a); // 释放内存 
}

void UseNewDelete(void) 
{ 
    Obj *a = new Obj; // 申请动态内存并且初始化 
    //… 
    delete a; // 清除并且释放内存 
}

由于内部数据类型的“对象”没有构造与析构的过程,对它们而言 malloc/freenew/delete 是等价的

因为 C++程序经常要调用 C 函数,而 C 程序只能用 malloc/free 管理动态内存

C的动态内存管理

//C的动态内存管理
int main()
{
    int n = 10;
    int *ipa = (int*)malloc(sizeof(int)*n);
    int *ipb = (int*)calloc(n,sizeof(int));
    ipa = (int*)realloc(ipa,sizeof(int)*n*2);
    //
    free(ipa);
    ipa = NULL;
    free(ipb);
    ipb = NULL;
    return 0;
}

malloc和free的使用

//函数malloc的原型如下: 
void * malloc(size_t size); 
//用 malloc 申请一块长度为 length 的整数类型的内存,程序如下: 
int *p = (int *) malloc(sizeof(int) * length);

//函数 free 的原型如下:
void free( void * memblock );
  • malloc返回值的类型是void *,所以在调用 malloc 时要显式地进行类型转换,将 void * 转换成所需要的指针类型。
  • malloc函数本身并不识别要申请的内存是什么类型,它只关心内存的总字节数。如 int 变量在 16 位系统 下是 2 个字节,在 32 位下是 4 个字节;而 float 变量在 16 位系统下是 4 个字节,在 32 位下也是 4 个字节。
  • 如果 p 是 NULL 指针, 那么 free 对 p 无论操作多少次都不会出问题。如果 p 不是 NULL 指针,那么 free 对 p 连续操作两次就会导致程序运行错误。

C++的动态内存管理

new和delete的使用

//C++的动态内存管理
//1、new运算符的使用
int main()
{
    int n = 10;
    int* ipa = new int(10); // 1 // 2;
    int* ipb = new int[n](10);
    int* ipc = new int[n] {1, 2, 3, 4, 5, 6, 7};
    delete ipa;
    delete[]ipb;
    delete[]ipc;
    return 0;
}

//2、new的函数方式使用
int main()
{
    int n = 10;
    int *ipa = (int*)::operator new(sizeof(int));
    // (int*)malloc(sizeof(int));
    int *ipb = (int*)::operator new(sizeof(int)*n);
    // (int*)malloc(sizeof(int)*n);
    ::operator delete(ipa);
    ::operator delete(ipb);
    return 0;
}

//3、定位new
int main()
{
    int n = 10;
    int* ipa = (int*)malloc(sizeof(int));
    int* ipb = (int*)::operator new(sizeof(int) * n);
    new(ipa) int(20);
    new(ipb) int[]{ 1,2,3,4,5,6,7,8,9 };
    free(ipa);
    ::operator delete(ipb);
    return 0;
}

new的种类

int *p1 = new int(20);

int *p2 = new (nothrow) int;//不抛出异常版本的new,返回值跟空判断。

const int *p3 = new const int(40);//开辟常量内存

//定位new  
int data = 0;
int *p4 = new (&data) int(50);
//在指定的内存上划分出4字节的内存赋值为50
cout << "data:" << data << endl;//data:50

定位new可以在指定的位置分配内存

int main()
{
		int n =10;
		int* ipa=(int*)ma1loc(sizeof(int));
		int* ipb = (int*)::operator new(sizeof(int) *n);

		new(ipa)int(20);
		new(ipb) int[]{ 1,2,3,4,5,6,7,8,9};
    
		free(ipa);
		::operator delete(ipb);

		return 0;
}

operator new 和 operator delete

当我们在C++中使用newdelete时,其实执行的是全局的::operator new::operator delete,不过这两个函数并没有重载new表达式或delete表达式。

可以重载operator newoperator delete来控制内存的分配和释放,但不能重载new表达式和delete表达式。也就是说,可以自定义的是实际的内存分配和释放,但不能自定义构造函数和析构函数的调用
我们提供新的operator new函数和operator delete函数的目的在于改变内存分配的方式,但是不管怎样,都不能改变new运算符和delete运算符的基本含义。

void *operator new(size_t);     //allocate an object
void *operator delete(void *);    //free an object

void *operator new[](size_t);     //allocate an array
void *operator delete[](void *);    //free an array
一条new的三步骤
  1. new表达式调用一个名为operator new(或operator new[])的标准库函数,该函数分配一块足够大的、原始的、未命名的内存空间以便存储特定类型的对象(或者对象的数组);
  2. 编译器运行相应的构造函数以构造这些对象,并为其传入初始值;
  3. 对象被分配了空间并构造完成,返回一个指向该对象的指针。
//new:分配空间--->调用构造函数初始化--->对象构造完成,返回一个指向该对象的指针。
// new表达式
std::string *sp = new std::string("a value");  // 分配并初始化一个std::string对象
std::string *arr = new std::string[10];        // 分配10个默认初始化的std::string对象
一条delete的两步骤
  1. 对所指对象或者对象数组执行对应的析构函数;
  2. 编译器调用名为operator deleteoperator delete[]的标准库函数释放内存空间。
//delete:调用析构函数--->释放空间
// delete表达式
delete sp;          // 销毁*sp,然后释放sp指向的内存空间
delete [] arr;      // 销毁数组中的元素,然后释放对应的内存空间

总结

对于内置类型 new / delete / malloc/free 可以混用。

区别:

1、 new/delete 是C++中的运算符。 malloc / free 是函数。

2、 malloc申请内存空间时,手动计算所需大小,new只需类型名,自动计算大小;

3、 malloc申请的内存空间不会初始化,new可以初始化;

4、 malloc的返回值为void*, 接收时必须强转,new不需要;

5、 malloc申请内存空间失败时,返回的是NULL,使用时必须判空;

new申请内存空间失败时抛出异常bad_alloc,所以要有捕获异常处理程序。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: malloc/freenew/delete 都是C/C++中的内存管理函数。malloc/freeC语言的内存管理函数,它们用于申请和释放内存空间,它们没有构造函数和析构函数,只能用于普通的内存管理。而new/deleteC++中的内存管理函数,它们用于申请和释放内存空间,它们有构造函数和析构函数,可以用于类的内存管理。 ### 回答2: malloc/freenew/delete是两种动态内存分配和释放的方式。 首先,malloc/freeC语言的标准库函数,而new/deleteC++中的操作符。 其次,mallocfree是通过调用标准库函数来分配和释放内存,而newdelete是通过调用运算符来完成。 此外,mallocfree只能用于分配和释放内存,它们并不能调用对象的构造函数和析构函数。而newdelete不仅可以分配和释放内存,还可以调用对象的构造函数和析构函数。 另外,malloc分配的内存空间的大小是以字节为单位的,而new分配的内存空间的大小是以对象为单位的。因此,使用malloc分配内存时,需要手动计算所需的空间大小并进行类型转换;而使用new分配内存时,会自动计算所需的空间大小,并进行类型检查。 最后,malloc/free返回的是void指针,需要进行类型转换后才能使用;而new返回的是对象的指针,不需要进行类型转换。 综上所述,malloc/freenew/delete的区别在于语法和功能上的不同。对于C语言来说,只能使用mallocfree来进行动态内存分配和释放;而对于C++来说,则推荐使用newdelete来进行动态内存分配和释放,并能够调用对象的构造函数和析构函数。 ### 回答3: malloc/freenew/delete是两种在C和C++中用于内存分配和释放的方法。 首先,mallocfreeC语言中的函数,而newdeleteC++中的操作符。 mallocfree是库函数,用于动态分配和释放内存。它们需要手动指定要分配的内存大小,并且返回的是一个void指针。由于返回的是void指针,因此必须进行类型转换,以便使用分配的内存。此外,malloc分配的内存大小可以是0,而free不能接受空指针作为参数。 而newdeleteC++中的操作符。new操作符用于在堆上分配内存,并且会自动调用相应类型的构造函数进行对象的初始化。在使用new操作符时,不需要手动指定内存大小,而是需要指定要分配的类型。delete操作符用于释放new操作符分配的内存,并且会自动调用相应类型的析构函数进行对象的清理。同时,delete操作符还可以正确处理数组类型的对象的释放。 综上所述,malloc/freenew/delete的区别包括以下几个方面: - 使用场景:malloc/free适用于C语言,而new/delete适用于C++语言。 - 操作符与函数:malloc/free是函数,需要手动指定内存大小,返回的是void指针;而new/delete是操作符,不需要指定内存大小,可以自动调用构造函数和析构函数。 - 初始化和清理:new操作符可以自动调用构造函数进行对象初始化,而delete操作符可以自动调用析构函数进行对象清理。 - 处理数组:delete操作符可以正确处理数组类型的对象的释放。 因此,在使用C++编程时,推荐使用new/delete来替代malloc/free,可以更方便地进行内存管理和对象的初始化和清理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值