C++指针解读(10)-- 动态内存分配

栈和堆是进程内存空间中非常重要的2块区域。栈用于存放程序临时创建的局部变量;堆用于存放进程运行中被动态分配的内存段。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上;当利用free等函数释放内存时,被释放的内存从堆中被剔除。

1、C动态内存分配

C语言动态内存分配相关的库函数有以下几个:

malloc、calloc、realloc、free这4个函数。

(1)malloc

void *malloc(unsigned int size);

函数的作用是分配一个长度为size个字节的连续空间。函数的返回值是所分配区域的第一个字节的地址。

如果函数未能成功地执行,则返回空指针NULL。

int* pv = (int*)malloc(5*sizeof(int));
if(pv != NULL){ //先检查函数调用是否成功
    for (int i = 0; i < 5; i++) {
        pv[i] = i + 1;
    }
}

(2)calloc

void *calloc(unsigned n, unsigned size);

函数的作用是分配n个长度为size个字节的连续空间,并同时清空内存。可用来给数组开辟动态存储空间。

int *p = (int*)calloc(8, 4);

分配8*4个字节的存储空间。

如果用malloc来达到同calloc的效果,则代码需要这么写:

int *p = (int*)malloc(8*4); //malloc不会清空内存,可调用memset清空内存
memset(p, 0, 8*4);

(3)realloc

void *realloc(void *p, unsigned int size);

如果已经通过malloc函数或calloc函数分配了空间,想改变其大小,可以用realloc函数重新分配。

int* pi = (int*)calloc(8, 4);
*pi = 4;
*(pi + 1) = 5;
printf(" %d\n", *(pi + 1)); //输出5

realloc(pi, 64);
printf(" %d\n", * (pi + 1)); //输出5。所以realloc不会破坏原来存储的数据

return 0;

realloc函数要点总结:

(3.1)realloc函数可以扩大存储空间,也可以缩小存储空间。

(3.2)realloc函数重新分配了新地址,旧指针无需调用free。

(3.3)一定不要这样调用:ptr = realloc(ptr, size),这样会使原来的ptr丢失而导致内存泄漏。

(3.4)如果调用realloc失败,返回NULL;但原内存空间不受影响。

(3.5)realloc很耗资源,能不用就不用。

(4)free

void free(void *ptr);

函数的参数是指向由malloc、calloc、realloc函数分配的内存地址,调用后这块内存返回给堆空间。

int *pi = (int*)malloc(4);
...
free(pi);

调用free函数后,指针pi指向的内存空间被释放,但指针pi依然指向这块已被释放的地址。

C++指针解读(10)-- 动态内存分配_第1张图片

此时,需要把NULL赋给指针pi:pi = NULL

重复free置为NULL的指针不会出错,但重复free非NULL指针一定会报错。

int* pi = (int*)calloc(8, 4);
free(pi);

pi = NULL;
free(pi); //重复free不会报错
free(pi); //重复free不会报错

2、C++动态内存分配

(1)new、delete

C++中通过new关键字进行动态内存申请,用delete关键字进行内存释放。

malloc、calloc、realloc函数是按字节数分配存储空间的;

但用new内存分配是基于类型进行的。

int* pi = new int(1); //分配内存时把值初始化为1
delete pi;

int* pv = new int[10];
delete[] pv;

(2)new关键字与malloc函数的区别

new关键字

malloc函数

new关键字是C++的一部分

malloc是由C库提供的函数

new以具体类型为单位进行内存分配

malloc以字节为单位进行内存分配

new在申请单个类型变量时可进行初始化

malloc不具备内存初始化的特性

(3)动态内存分配异常机制

用malloc分配内存空间可能会失败,用new分配内存空间也可能失败。C++提供了两种标准机制来检查分配是否成功。

(3.1)bad_alloc异常

默认情况下,在分配失败时会抛出bad_alloc类型的异常,如果此异常未处理,则程序终止。

int* pv = new int[10];

(3.2)nothrow

使用nothrow后,在内存分配失败时,不抛出bad_alloc异常;此时new返回的空指针。

int* pv = new (nothrow) int[10];
if (pv != nullptr) {
    ... ...
}

你可能感兴趣的:(C++指针解读,c++,指针,动态内存分配)