1、内存的简要了解c++
说到内存,不少人应该都多多少少有点了解了,咱们在这再稍微多说几句:编程
通常咱们能够把内存理解为三个部分:静态区,栈,堆。有些朋友搞不清到底什么是栈什么是堆,堆栈有多人会认为是堆和栈,两个放在一块。其实否则,其中咱们口中讲的堆栈就是栈,而不是堆。堆的英文是heap ;栈的英文是stack(也翻译为堆栈)。函数
存储内容:spa
静态区:保存自动全局变量和static变量(包括static全局和局部变量)。静态区的内容在整个程序的生命周期内都存在,有编译器在编译的时候分配(数据段(存储全局数据和静态数据)和代码段(可执行的代码/只读常量))。翻译
栈:保存局部变量。栈上的内容只在函数范围内存在,当函数运行结束的时候,这些内容也会自动销毁。其特色是效率高可是空间大小有限。3d
堆:由malloc系列函数或者new操做符分配的内存。其生命周期由free和delete决定。在没有释放以前一直存在,直到函数结束。其特色是使用灵活,空间比较大,但容易出错。指针
2、malloc、calloc、realloccode
三者的简单对比:对象
malloc 函数原型:(void*)malloc(unsigned size);(字节数)blog
malloc函数在内存中开辟的是一块连续的空间,size是所须要空间的长度,开辟的大小为size*参数类型,开辟完以后返回这块空间的首地址。
calloc 函数原型:void* calloc(size_t numElements, size_t sizeOfElements);(元素的个数, 单个元素的字节数)
和malloc类似,它也是开辟一块连续的空间,空间的大小为:元素的个数*单个元素的字节数。
realloc 函数原型:void* realloc(void* ptr, unsigned newsize);(地址,字节数)
给一个已经分配地址的指针从新分配空间,参数ptr为原有的空间指针,newsize为从新申请的地址长度。它与malloc的区别就是若是你给的指针是NULL,那么你使用的就是malloc,若是你给出的指针是一个已经分配了地址的指针(ptr),那么你使用的就是realloc。
区别:
(1)函数malloc不能初始化所分配的空间,而函数calloc能,也就是说,若是由malloc函数分配的空间原来没有被分配过,则其中每一位均可能是0;反之,若是这一块数据块原来被分配过,那里面可能遗留着各类各样的数据。因此,当你在使用malloc开辟一块新空间的时候,要从新初始化那一块空间(通常调用memset函数来初始化空间)。不然在屡次释放、开辟以后,可能会出现使用错误。
(2)calloc函数会将所分配的内存空间中的每一位都初始化为0(这也是它和malloc的主要不一样处之一)。也就是说,若是你是为字符类或者整形类的元素分配空间,那么这些元素会保证被初始化为0;若是你是为指针类函数分配内存,那么这些元素都会被初始化为空指针。
(3)malloc向系统申请size个字节的空间,申请完以后返回的是这个空间的首地址,类型为void*,而void*表示未肯定的类型,在c/c++中void*能够被强转成任意类型的指针。
(4)realloc能够对给定的指针所指向的空间进行扩大或者缩小,不管是扩大仍是缩小,原有内存中的内容将保持不变(若是对于缩小以后的空间,被缩小的那部分空间内的数据仍是会丢失)。realloc并不保证调整后的内存空间和原来的内存空间保持同一个地址。相反,realloc指针极可能指向一个新的地址。
(5)realloc是从堆上分配空间的,但当你进行扩大的时候,realloc会试图从堆上现存的数据后面的那些字节中获取附加的字节,若是能知足,就恰好。但若是后面的字节数不够,其就会使用堆上第一个有足够大小的自由块,而后将现存的数据拷贝到新的位置,将老块放回到堆上。在这个过程当中,数据会被移动。也就是说,当你使用realloc的时候,数据可能被移动。
3、有关malloc的一些扩展(选自《高质量c/c++编程指南(林锐)》)
malloc
malloc的原型:(void*)malloc(int size)(int也能够是unsigned,int只是其中的一种特例)
malloc函数的返回值是一个void类型的指针,参数为int类型数据,即申请分配的内存大小,单位是byte。内存分配成功以后,malloc函数返回这块内存的首地址。你须要一个指针来接受这个地址。可是因为函数的返回值是void*类型,因此必须强制转换成你所接收的类型。也就是说,这块内存未来要存储什么类型的数据。好比:
char* p = (char*)malloc(100);
在堆上面分配了100个字节内存,返回这块内存的首地址,把地址强制转换成char*类型后赋给char*类型 的指针变量p。同时告诉咱们这块内存未来用来存储char*类型的数据。也就是说你只能经过指针变量p来操做这块内存。这块内存自己并无名字,对它的访问是匿名访问。
内存释放
有分配就必定有释放。malloc对应的就是free函数。free函数只有一个参数,就是要释放的内存块的首地址。好比:free(p);
free函数作的事情:斩断指针变量与这块内存的关系。就像上面的例子同样malloc函数开辟的这一个数据块空间是属于p的,你只能经过p来访问这一块数据块空间,而free函数作的事情就是斩断malloc和p之间的联系。可是p指针自己存放的地址并无发生变化,只是它对指针所指向的那块内存已经没有全部权了,不能对内存块进行操做。而那块内存块里面的数据也没有被改变,只是你没有办法去访问或者修改那块数据快中的内容了。
malloc和free是一一对应的,若是malloc两次可是只free一次就会存在内存泄漏,若是malloc一次可是free了两次,就会出错(第一次使用free的时候,malloc所开辟的空间就已经被释放,第二次使用free就无内存空间能够释放了,这种对内存的误操做就有可能会致使程序的崩溃)。
函数的内存释放完后,必定要把p指针置为NULL。为何?
从上面能够看出,free掉以后p只是切断了和内存空间的关系,可是p指针自己内部依旧存在一个地址,若是不把它置成空,那这个指针就会变成一个野指针(悬垂指针),早晚会出事。
1 char* p = (char*)malloc(100); 2 strcpy(p, "hello"); 3 free(p);//能够看到这边已经释放了p所指向的那一块空间,可是p自己存储的地址并无改变 4 if(NULL != p)//判断不起做用,起不到防御做用 5 { 6 strcpy(p, "world");//p没有分配空间,出错。 7 }
4、new/delete
前头讲了不少但好像尚未讲到c++的动态内存这方面。下面咱们来进行一些讨论。
咱们知道c++是兼容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,我在这就不作了(其实new和delete是不能重载的,即便你进行了重载,也只是重载了operator new和operator delete)。
有关operator new/operator delete operator new[]/operator delete[]
总结:
1.operator new/operator delete operator new[]/operator delete[]的用法和malloc/free同样。
2.它们只负责分配空间/释放空间,不会调用对象构造函数和析构函数来初始化/清理对象。
3.实际operator new/operator delete 只是malloc和free的一层封装。
5、new和delete在内存中所作的事