C.C++动态内存管理的一些问题

来源:互联网 发布:人工智能学什么专业 编辑:程序博客网 时间:2024/05/29 16:33

关于C.C++动态内存管理的一些问题,我们做一下几点讲解:

1.C的动态内存管理

C中主要以以下几个函数进行动态管理内存:
(1)void* malloc(size_t size) 
分配长度为size字节的内存块,如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。
int* p=malloc(sizeof(int))
(2)void* calloc(size_t sz, size_t size)
在内存的动态存储区中分配sz个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。一般使用后要使用 free(起始地址的指针) 对内存进行释放,不然内存申请过多会影响计算机的性能,以至于得重启电脑。如果使用过后不清零,还可以使用指针对该块内存进行访问。
char* str=(char*)calloc(10,sizeof(char));
跟malloc的区别:
calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。
(3)void* realloc(void* p, size_t size)
指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小),新的大小一定要大于原来的大小,不然的话会导致数据丢失!
先判断当前的指针是否有足够的连续空间,如果有,在原来空间的基础上扩充,并且将原来空间起始地址指针返回,如果空间不够,先按照指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来的空间(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。
如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。
(4)void* free(void* p)
free函数是从p指向的起始地址开始,释放该空间
注意;一般在程序出现内存错误很有可能就是动态内存的释放出问题了,所以在使用动态内存时一定要注意释放的问题,在c中还需要注意在释放完动态内存后将指向动态内存的指针置为NULL,避免形成野指针,好了c中的动态内存管理就回忆到这,毕竟我想说的是c++的动态内存管理问题。

2.再看看C++动态内存管理使用什么武器?
       c++中使用new和delete实现动态内存管理。new和delete实现动态管理对象,new[]和delete[]实现动态管理对象数组。c++中的new和delete运算符均使用我们c中学过的malloc和delete函数实现动态内存的开辟。
c++中使用new/delete或new[]/delete[]实现动态管理,特别需要提醒的是在动态内存的管理中一定要注意new/delete,new[]/delete[],malloc/free一定要注意匹配使用。

3.大家肯定想既然c++兼容c,为什么不直接使用c中的malloc/free,而要使用new/delete,首先我们需要了解一下二者的区别和联系。
C中的malloc/free和C++中的new/delete的区别和联系?

1. 它们都是动态管理内存的入口。
2. malloc/free是C/C++标准库的函数,new/delete是C++操作符。
3.malloc/free只是动态分配内存空间/释放空间。new/delete除了分配空间还会调用构造函数和析构函数进行对象的初始化与清理(清理成员)。
4. malloc/free需要手动计算类型并且返回值会void*,new/delete可以自动计算类型的内存的字节数,返回对应类型的指针

c++中的new和delete的内部还是依靠malloc/free实现的,在使用我们new时我们调试进入内部发现,new调用了operator new(),delete调用了operator delete(),c++ 中还有其他几个内存管理接口,new/delete表达式的实现依靠库中的这几个函数。
void * operator new (size_t size);
void operator delete (size_t size);
void * operator new [](size_t size);
void operator delete[] (size_t size);

这几个函数在内部实现空间的开辟和释放,他们只负责空间的开辟和释放,不会调用构造函数构造对象也不会调用析构函数清理对象。实际上他们只是malloc/free的封装。
4.总结一下:
new做了两件事
1. 调operator new分配空间。
2. 调构造函数初始化对象。
delete也做了两件事
1. 调析构函数清理对象
2. 调operator delete释放空间
new[N]
1. 调operator new分配空间。
2. 调N次构造函数分别初始化每个对象。
delete[]
1. 调N次析构函数清理对象。
2. 调operator delete释放空间。
特别需要注意的是delete[]调用了N此析构函数,N在哪保存呢?
实际上new[]在调用operator[]时在最前面多开辟了四个字节用来存放创建对象的个数。(这种情况只是发生在自定义类型,并且显示写出析构函数的时候)
5.我们可以使用定位new表达式来模拟实现new的功能,我们先来了解下new表达式:
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
new (place_address) type
new (place_address) type(initializer-list)
place_address必须是个指针,initializer-list是类型的初始化列表。
模拟实现new[]/delete[]

































































原创粉丝点击