malloc、free与new、delete

【1】malloc与free  和 new与delete

(1)malloc与free是C++/C语言的标准库函数。new/delete是C++的运算符,不是库函数。它们都可以申请动态内存和释放内存。

(2)对于非内部数据类型的对象而言,用malloc/free无法满足动态对象的要求(对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数)。

(3)由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此,C++语言需要可以完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。

(4)都是在堆(heap)上进行动态的内存操作。用malloc函数需要指定内存分配的字节数并且不能初始化对象。new会自动调用对象的构造函数。

delete 会调用对象的destructor,而free 不会调用对象的destructor。

【2】描述内存分配方式以及它们的区别?

(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如:全局变量,static 变量。

(2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。

(3)从堆上分配(动态内存分配)。程序在运行的时候用malloc 或 new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。

动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。

【3】malloc 与 free

(1)malloc函数分配的空间一定要用free函数释放掉。

(2)free(p) 仅仅指释放了malloc分配的空间,但是p指针仍然不为空,所以,在free函数释放后一般要置空!防止野指针!

(3)非空指针只可以释放一次。

(4)一般两者搭配使用。

(5)malloc 与 free示例代码如下:

复制代码
 1 #include<iostream>
 2 #include<malloc.h>
 3 using namespace std;
 4 
 5 void main()
 6 {
 7     int *p = NULL ;  //指针定义最好初始化为空(程序员基本素养,哈哈)
 8 
 9     //空指针释放多次没有任何意义
10     free(p);   //编译通过!运行通过!一次
11     free(p);   //编译通过!运行通过!二次
12 
13     p = (int *)malloc(sizeof(int)*5);
14     if(NULL == p)
15     {
16         cout<<"malloc failed!"<<endl;
17         exit(1);
18     }
19     else
20     {
21         p[0] = 0;       //注意赋值形式
22         p[4] = 4;
23 //        p[5]=100;       //编译可以通过,但是运行错误error!!!因为p[5]越界
24 
25         cout<<"p[4]: "<<p[4]<<endl;   //4
26           
27         cout<<"p[1]: "<<p[1]<<endl;   //随机数!!
28      }
29 
30     free(p);  //malloc申请空间使用free释放(固定搭配)
31 
32     if(NULL == p)
33     {
34         cout<<"free(p) p == NULL"<<endl;
35     }
36     else
37     {
38         cout<<"free(p) p != NULL"<<endl;   //野指针!!!
39 //        p[2] = 100;  //编译可以通过,运行时崩溃!!因为野指针所致。
40     }
41 
42 //    free(p);    //编译可以通过,运行时崩溃!! 因为已经释放了一次,再次释放导致错误。
43 
44     p = NULL;  //彻底预防了它的破坏性
45 
46     //........
复制代码

【4】new 与 delete

(1)new的三种形态

到目前为止,C++相关资料书籍谈及的new至少代表以下三种含义:

<1>new operator : new 运算符 (当然,书面称法。个人觉得还是按照习惯称作关键字new,以下此种形态均称关键字 new

<2>operator new : 操作符  new(当然,书面称法。个人觉得称为new函数,以下此种形态均称new函数

<3>placement new: 定位 new(C++primer上的称法)

(2)关键字new

平常我们使用最多的就是关键字new。它由语言内建 ,不能重载 ,不能改变其行为 。

关键字new在堆上动态创建一个对象时,它实际上做了三件事:

1:获得一块内存空间、

2:调用构造函数、

3:返回正确的指针。

当然,如果我们创建的是内置类型的变量,那么第二步会被省略。

示例代码如下:

复制代码
 1 #include<iostream>
 2 #include<assert.h>
 3 using namespace std;
 4 
 5 class A 
 6 { 
 7     int i; 
 8 public: 
 9     A(int _i = 2) :i(_i*_i) 
10     {
11         cout<<"constructor   "<<this<<endl;
12     } 
13     void Print() 
14     { 
15         cout<<i<<endl; 
16     } 
17     ~A()
18     {
19         cout<<"destructor  "<<this<<endl;
20     }
21 
22 }; 
23 
24 void main()
25 {
26     /*
27      *内置类型示例代码
28      */
29     int *p1 = NULL;
30     p1 = new  int(10);
31     assert(p1 != NULL);
32     cout<<*p1<<endl;     //10
33     delete  p1;
34     p1 = NULL;
35 
36 
37     int *p2 = NULL;
38     p2 = new  int[5];   //申请5份int类型大小的空间
39     assert(p2 != NULL);
40     delete []p2;       //释放数组变量
41     p2 = NULL;
42 
43     /*
44     *自定义类型示代码
45     */
46     A  *p3 = NULL;
47     p3 = new A;       //调用默认复合构造函数
48     assert(p3 != NULL);
49     p3->Print();      //4
50     cout<<"delete obj"<<endl;
51     delete p3;
52     p3 = NULL;
53 
54     A  *p4 = NULL;
55     p4 = new A[5];       //调用默认复合构造函数   注意数组
56     assert(p4 != NULL);
57     p4[0].Print();    //4
58     cout<<"delete obj"<<endl;
59     delete []p4;
60     p4 = NULL;
61 
62     A  *p5 = NULL;
63     p5 = new A(10);       //调用默认复合构造函数   注意区别
64     assert(p5 != NULL);
65     p5[0].Print();    //100
66     cout<<"delete obj"<<endl;
67     delete p5;
68     p5 = NULL;
69 
70 }
71 
72 /*
73 10
74 constructor   00644B48
75 4
76 delete obj
77 destructor  00644B48
78 constructor   00644BDC
79 constructor   00644BE0
80 constructor   00644BE4
81 constructor   00644BE8
82 constructor   00644BEC
83 4
84 delete obj
85 destructor  00644BEC
86 destructor  00644BE8
87 destructor  00644BE4
88 destructor  00644BE0
89 destructor  00644BDC
90 constructor   00644B48
91 100
92 delete obj
93 destructor  00644B48
94  */
复制代码

(3)函数new

关键字new第一步分配内存实际上是通过调用new函数来完成的,而这里的new就是像加减乘除一样的操作符,因此是可以重载的。

new函数默认情况下首先调用分配内存的代码,尝试得到一段堆上的空间,如果成功就返回;如果失败,则转而去调用一个new_hander,然后继续重复前面过程。

如果我们对这个过程不满意,就可以重载operator new,来设置我们希望的行为。

示例代码如下:

复制代码
  1 #include<iostream>
  2 #include<assert.h>
  3 #include<new>
  4 using namespace std;
  5 
  6 class A 
  7 { 
  8     int i; 
  9 public: 
 10     A(int _i = 2) :i(_i*_i) 
 11     {
 12         cout<<"constructor   "<<this<<endl;
 13     } 
 14     void Print() 
 15     { 
 16         cout<<i<<endl; 
 17     } 
 18     ~A()
 19     {
 20         cout<<"destructor  "<<this<<endl;
 21     }
 22 
 23 }; 
 24 /*
 25  *重载全局new/delete函数
 26  */
 27 void * operator new(size_t size)
 28 {
 29     cout<<" overload operator new "<<endl;
 30     void *p = malloc(size);
 31     return (p);
 32 }
 33 void operator delete(void *p)
 34 {
 35     cout<<" overload operator delete "<<endl;
 36     free(p);
 37 }
 38 
 39 void main()
 40 {
 41     /*
 42      *内置类型示例代码
 43      */
 44     int *p1 = NULL;
 45     p1 = (int *)::operator new(sizeof(int));
 46     new(p1) int(10);   //第一种赋值方式  
 47     assert(p1 != NULL);
 48     cout<<*p1<<endl;       //10
 49     ::operator delete(p1);
 50     p1 = NULL;
 51 
 52 
 53     int *ptr = NULL;
 54     ptr = (int *)::operator new(sizeof(int));
 55     *ptr = 100;    //第二种赋值方式  
 56     assert(ptr != NULL);
 57     cout<<*ptr<<endl;      //100
 58     delete  ptr;
 59     ptr = NULL;
 60 
 61     int *p2 = NULL;
 62     p2 = (int *)::operator new(sizeof(int) * 5);   //申请5份int类型大小的空间
 63     assert(p2 != NULL);
 64     for(int i = 0; i < 5; ++i)
 65     {
 66         p2[i] =  i + 10;   //数组变量的赋值
 67     }
 68     for(int i = 0; i < 5; ++i)
 69     {
 70         cout<<p2[i]<<endl;   //10 11 12 13 14 
 71     }
 72     ::operator delete[] (p2);       //释放数组变量
 73     p2 = NULL;
 74 
 75     /*
 76     *自定义类型示代码
 77     */
 78     A  *p3 = NULL;
 79     p3 = (A *)::operator new(sizeof(A));     
 80     assert(p3 != NULL);
 81     new(p3) A(10);
 82     p3->Print();       //100
 83     cout<<"delete obj"<<endl;
 84     p3->~A();    //先调用对象析构函数
 85     ::operator delete(p3);  //再释放申请内存
 86     p3 = NULL;
 87 
 88     //注意差别
 89     A  *p4 = NULL;
 90     p4 = (A *)::operator new(sizeof(A));     
 91     assert(p4 != NULL);
 92     new(p4) A(10);
 93     p4->Print();       //100
 94     cout<<"delete obj"<<endl;
 95     ::operator delete(p4);  //直接释放申请内存
 96     p4 = NULL;
 97 }
 98 
 99 /*
100 overload operator new
101 10
102 overload operator delete
103 overload operator new
104 100
105 overload operator delete
106 overload operator new
107 10
108 11
109 12
110 13
111 14
112 overload operator new
113 constructor   00194B48
114 100
115 delete obj
116 destructor  00194B48
117 overload operator delete
118 overload operator new
119 constructor   00194B48
120 100
121 delete obj
122 overload operator delete
123 
124  */
复制代码

下面比较new关键字与new函数的区别:

<1>new关键字

int *ptr = new  int(100);

1:分配内存; 2:赋初始值; 3:类型自动匹配; 4:大小自动。

<2>new函数

int *ptr = (int *)::operator new(sizeof(int) * 5);

1:分配内存; 2:无初始化; 3:类型转换; 4:大小手动。

(4)定位new

定位new是用来实现定位构造的,因此可以实现关键字new三步操作中的第二步,也就是在取得了一块可以容纳指定类型对象(变量)的内存后,在这块内存上构造一个对象(变量)。

示例代码如下:

关于对象的构建,上面new函数的示例代码中已经很具体了。在此,特别示例定位new也可以构造栈上的内存。

复制代码
 1 #include<iostream>
 2 #include<assert.h>
 3 //#include<new.h>   //有些资料书提醒必须加这个头文件,VS2010下可以省略。
 4 using namespace std;
 5 
 6 class A 
 7 { 
 8     int i; 
 9 public: 
10     A(int _i = 2) :i(_i*_i) 
11     {
12         cout<<"constructor   "<<this<<endl;
13     } 
14     void Print() 
15     { 
16         cout<<i<<endl; 
17     } 
18     ~A()
19     {
20         cout<<"destructor  "<<this<<endl;
21     }
22 
23 }; 
24 
25 
26 void main()
27 {
28     char s[sizeof(A)]; 
29     A* p = (A*)s; 
30     new(p) A(3);   //定位new的用法
31     p->Print(); 
32     p->~A();  //不过必须要显式调用析构函数
33 }
34 
35 /*
36 constructor   0038F8EC
37 9
38 destructor  0038F8EC
39  */
复制代码

这里“new(p)   A(3)”这种奇怪的写法即是定位new的用法,它实现了在指定内存空间用指定类型的构造函数来构造一个对象的功能,后面A(3)就是对构造函数的显式调用。

通过上面的例子以及这个例子,我们可以看到这块指定的地址既可以是栈,又可以是堆,定位new对此不加区分。

但是,除非特别必要,不要直接使用定位new ,这毕竟不是用来构造对象的正式写法,只不过是new函数的一个步骤而已。

使用关键字new地编译器会自动生成对定位new的调用的代码,因此也会相应的生成使用delete时调用析构函数的代码。

如果是像上面那样在栈上使用了定位new,则必须手工调用析构函数,这也是显式调用析构函数的唯一情况: p->~A();

当我们觉得默认的关键字new对内存的管理不能满足我们的需要,而希望自己手工的管理内存时,定位new就有用了。

STL中的allocator就使用了这种方式,借助定位new来实现更灵活有效的内存管理。 

【5】new的基本使用指南

(1)如果想在堆上建立一个对象,应该用关键字new 。它既分配内存又为对象调用构造函数。

(2)如果仅仅想分配内存,就应该调用 new 函数;它不会调用构造函数。

如果想定制在堆对象被建立时的内存分配过程,你应该写自己的new 函数,然后使用new关键字, new 关键字会调用定制的 operator new .

(3)如果想在一块已经获得指针的内存里建立一个对象,应该用 定位new 。定位new 主要适用于:

<1>在对时间要求非常高的应用程序中,因为这些程序分配的时间是确定的;

<2>长时间运行而不被打断的程序;

<3>以及执行一个垃圾收集器(garbage collector)。

转: http://www.cnblogs.com/Braveliu/archive/2013/01/10/2854211.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: mallocfree是C语言中的动态内存分配和释放函数,用于在程序运行时动态地分配和释放内存空间。malloc函数用于分配一块指定大小的内存空间,free函数用于释放已分配的内存空间。 newdelete是C++语言中的动态内存分配和释放运算符,用于在程序运行时动态地分配和释放内存空间。new运算符用于分配一块指定大小的内存空间,并返回指向该内存空间的指针,delete运算符用于释放已分配的内存空间。 总的来说,mallocfree是C语言中的动态内存分配和释放函数,newdelete是C++语言中的动态内存分配和释放运算符。它们的使用方法和功能类似,但是在C++中,newdelete还可以用于对象的构造和析构。 ### 回答2: 1. mallocfree 它们是C语言中的动态内存分配和释放函数,用于动态分配和释放内存,即在程序运行时根据需要从系统中分配出一块连续的、指定大小的内存,并返回指向这块内存的指针;当程序不需要使用这块内存时,使用free函数将其释放回内存。由于mallocfree是C语言中的函数,因此在使用时需要手动指定内存大小,且不支持自动释放内存。 2. newdelete 它们是C++语言中的动态内存分配和释放方式,和malloc/free相比,newdelete更加方便、安全,且支持自动释放内存new关键字可以自动计算需要的内存大小并返回对应类型的指针,delete关键字可以自动释放内存,而无需手动指定内存大小。 newdelete内存管理是面向对象的,它们可以调用构造函数和析构函数来初始化和清除对象,可以确保正确的内存布局和类型安全,这对于C++编程来说非常重要。 3. 区别对比 从功能上来说,mallocfree是C语言中的函数,用于动态内存分配和释放,需要手动指定内存大小,不支持自动释放内存;而newdelete是C++语言中的关键字,支持自动计算内存大小、自动调用类型的构造函数和析构函数、自动释放内存。 从安全性和易用性上来说,new/deletemalloc/free更安全、更方便,由于支持自动计算内存大小和类型安全,可以避免因内存管理不当而发生错误。同时,new/delete也更加适用于面向对象的程序设计,可以自动调用构造函数和析构函数,确保对象的正确创建、初始化和清除。因此,在C++编程中,建议使用newdelete进行动态内存管理。 总之,malloc/freenew/delete都是动态内存管理的方式,根据不同编程语言和场景需求,选择适合的动态内存分配和释放方式非常重要,同时注意内存分配和释放的规范和安全性。 ### 回答3: mallocfreenewdelete 都是用于动态内存分配和释放的关键字。它们在使用方式、机制、效率和能力上存在差异。 1. mallocfree malloc 是 C/C ++ 程序中用于动态分配内存的函数,它会根据用户的需求分配一块指定大小的内存块并返回其首地址,通常用于分配结构体或数组等动态内存。而 free 用于释放之前分配的由 malloc 分配的内存块,将内存块标记为可重用状态。 虽然 mallocfree 可以做到动态分配和释放内存,但是它们却没有处理对象的构造和析构,因此在使用过程中,如果需要先执行构造函数再分配空间或者先释放空间再执行析构函数,就需要用到以下两个关键字。 2. newdelete newdelete 是 C++ 中的关键字,它们不仅可以进行动态内存的分配和释放,而且还可以调用对象的构造和析构函数,能够在对象构造时自动执行构造函数,在对象销毁时自动执行析构函数,因此是一种更高级别的内存管理方式。 new 用于分配动态内存并调用构造函数来初始化对象,而 delete 用于调用析构函数并释放分配的内存,从而在对象生命周期的开头和结尾负责构造函数和析构函数的调用。 总之,mallocfree 是 C 语言的标准库关键字,而 newdelete 是 C++ 的关键字,它们之间的区别在于对于对象是否需要额外的构造函数和析构函数的调用等方面。因此,在实际的开发过程中,应根据需要选择合适的内存分配和释放方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值