c/c++动态内存总结

C动态内存分配:malloc / realloc / calloc

1)void *malloc( size_t size );

malloc的参数是用户所需内存空间大小的字节数,不会对申请成功的内存初始化。

malloc 申请空间时并不是需要多少就申请多少,而是会多申请一些空间:

      a.多申请一个32字节的结构体,里面对申请的空间进行描述,

      b.在申请的空间前后会各多申请 4 个字节的空间,这就是保护机制,当你操作不当越界了,这 8 个字节的内容会改变,操作系统会检查前后 4 个字节是否改变了,以此判断是否越界了。   

                    

                  

 

 

 

2)void *calloc( size_t _count, size_t _size);

calloc的参数:第一个:元素的个数,第二个:单个元素所占字节;会把申请成功的空间初始化为 0

 

3)void *realloc( void *ptr, size_t size );

 

 realloc的参数:第一个:地址,第二个:字节数
  对于 realloc 的第一个参数:
    如果指向空,那么此时realloc 就和 malloc 是一样的;
    如果不为空,那么就将即将要申请的空间与原空间进行比较。
        如果要申请的空间比原空间小,就将原空间缩小,并返回原空间首地址
        如果要申请的空间比原空间大,那么分两种情况:
        第一种:新旧空间之差小于原空间大小,直接在原空间进行延伸,并返回原空间的首地址。
        第二种:新旧空间之差大于原空间的大小,那么直接开辟新空间,并将原空间的数据拷贝到新空间,并返回新空间首地址。

 

 

共同点:

都是从堆上进行动态内存分配

释放内存都是需要使用free函数来释放

三者的返回值都是void*

都需要强制类型转换

都需要对申请出的空间判空(因为申请内存失败会返回空)

 

 

 

C++动态内存分配:new

1、不用强制类型转换;

2、不用对申请出来的空间进行判空;

3、可以申请时初始化这段空间。

 

 当用new创建对象时:

new:先将对象的空间开辟成功,然后调用构造函数完成对象的初始化。
delete:先调用析构函数将对象中的资源清理,然后释放对象占用的空间

如果对一个内部有资源的自定义类型使用 malloc 开辟内存,此时调用 delete 进行空间的释放,程序就会崩溃。因为 malloc 只负责开辟空间,并不会调用对象的构造函数对其成员变量进行初始化,那么内部的成员变量是没有分配空间的,当我们调用 delete 时,delete会先对对象进行资源清理,但是对象里的资源 malloc 并没有给其分配,所以我们清理的时候是非法的操作

 

对于内部有资源的自定义类型,使用 new 开辟的空间使用 free 释放,会造成内存泄漏,因为 free 并不会调用析构函数清理对象的资源,因此会造成资源泄漏。

 

 new一个对象:

new创建类对象需要指针接收,一处初始化,多处使用

new创建类对象使用完需delete销毁

new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间、

new对象指针用途广泛,比如作为函数返回值、函数参数等

频繁调用场合并不适合new,就像new申请和释放内存一样

 

new申请的对象,则只有调用到delete时再会执行析构函数,如果程序退出而没有执行delete则会造成内存泄漏;
CTest* pTest = new CTest();
delete pTest;

普通方式创建方式,使用完后不需要手动释放,该类析构函数会自动执行;
CTest mTest;

 


总结用法(语法格式):
1.malloc

 函数原型:

void *malloc( size_t size );

1)返回值是void*,需要强转

2)只有一个参数,表示用户所需内存空间大小的字节数。

3)只分配,不初始化。

int *p;
p
= (int *)malloc(sizeof(int));

 

2.calloc

 

函数原型

void *calloc( size_t _count, size_t _size);

1)返回值void *,需要强转

2)两个参数,第一个:元素的个数,第二个:单个元素所占字节

3)自动初始化为0.

int *p = (int *)calloc(20, sizeof(int)); //申请20个int类型控件,每个大小sizeof(int);

 

 

3.realloc

函数原型

void *realloc( void *ptr, size_t size );

 

1)返回值void*,需强转

2)两个参数,第一个:地址,第二个:字节数

3)主要用于对动态内存进行扩容。

               如果指向空,那么此时realloc 就和 malloc 是一样的;
    如果不为空,那么就将即将要申请的空间与原空间进行比较。
        如果要申请的空间比原空间小,就将原空间缩小,并返回原空间首地址
        如果要申请的空间比原空间大,那么分两种情况:
        第一种:新旧空间之差小于原空间大小,直接在原空间进行延伸,并返回原空间的首地址。
        第二种:新旧空间之差大于原空间的大小,那么直接开辟新空间,并将原空间的数据拷贝到新空间,并返回新空间首地址。

const int size = 2000;
int
*p = (int *)malloc(20*sizeof(int)); //malloc动态申请 int *pp = (int *)realloc(p, size*sizeof(int));//扩容

(1,2,3均使用free(p);释放内存)

 

4.new

int *p=new int[10];   //创建一个包含10个int的数组
delete[]p;//[]告诉程序应释放整个数组,而不仅仅是指针指向的元素。

注意:如果使用new不带方括号,则delete也不带;如果new有方括号,则delete野应带方括号。

int *p1=new int;
int *p2=new int [500];
delete [] p2;
delete p1;

 

posted @ 2020-03-15 08:08  坦坦荡荡  阅读(265)  评论(0)    收藏  举报