5,当一个动态分配的内存块不再使用时,应该调用free()把它归还给可用内存池,内存被释放后便不能被访问。
这几个函数的原型如下: void* malloc(size_t size); void* realloc(void* ptr,size_t new_size); void* calloc(size_t num_elements,size_t element_size);
void free(void* pointer);
区别: 函数malloc()在内存的动态存储区中分配一块长度为size字节的连续区域,参数size为所需内存空间的长度,返回该区域的首地址。他不能初始化所分配的内存空间(calloc函数可以做到),如果由malloc函数分配的内存空间原来没有被使用过,则其中的每一位都可能是0,如果这部分内存曾经被分配过,则其中可能遗留有原先的数据,综上,使用malloc函数的程序开始时能正常进行,但一段时间后可能会出现问题(内存空间已经被重新分配)。再一个malloc()向系统申请分配的指定size个字节的内存空间,返回类型是void*(未确定类型的指针),C,C++规定,void*类型可以强制转换为任何其他类型的指针。 函数calloc()会将分配的内存空间中的每一位都初始化为0. realloc()可以给指定的指针所指向的内存空间进行大小的调整,内存扩张不会引起内容的变化,而缩小会导致缩小的那部分其中的内容丢失。再一个realloc()并不能保证调整后的内存空间和原来的内存空间地址相同,相反,realloc返回的指针很可能指向一个新的地址(realloc()是从堆上分配内存的,当扩大一块内存空间时,realloc()试图直接从堆上现存的数据后面的那些字节中获得所需的字节,如果够则直接开辟,如果不够则会使用堆上一个足够大的自由块,现存的数据然后被拷贝至新的地址空间,而老块则放回到堆上,这说明了一个问题:原数据可能被移动。)。 总结: 1,如果请求的内存分配失败,malloc,calloc,realloc函数都返回的将是一个NULL指针。因此对每个从malloc返回的指针都进行检查,确保并非为NULL。错误的访问分配内存之外的区域所引起的后果类似越界访问一个数组,但这个错误可能破坏可用的内存池,引起程序失败。如果一个指针不是从早先的malloc等函数返回的,它不能作为参数传递给free函数。 2,你也不能只释放一块内存的一部分。 3,内存泄漏是指内存被动态分配之后,当他不再使用时未被释放。内存泄漏会增加程序的体积,有可能导致程序或系统的崩溃。但内存泄漏仅仅指程序在运行时,程序退出后,OS将回收所有的资源。 C++动态内存分配 1,C++通过new和delete来管理动态内存分配(new和delete动态管理对象,new[]和delete[]动态管理内存数组) 2, int* p0 = new int; //动态分配4个字节(1个int)的内存空间 int* p1 = new int(3);//动态分配4个字节(1个int)的内存空间,初始化为3 int* p2 = new int[3];//动态分配12个字节(1个int)的内存空间 delete p1; delete[] p2; 注:malloc/free,new/delete,new[]/delete[]一定要匹配使用,否则可能出现内存泄漏或程序崩溃的问题。 3,内存管理 int a = 1; static int b = 1; void test() { int c = 1; static int d = 1;
}
全局变量,静态全局变量,局部变量,静态局部变量的区别? 全局变量与静态全局:主要是连接属性不同,静态全局变量只能在当前原文件内使用。而全局变量哪里都能使用。
局部变量与静态局部变量:局部变量创建在栈上,静态局部变量创建在静态区,这导致他们生命周期不同,静态局部创建好不再销毁,直到程序结束。而局部变量出了它的作用域就自动销毁。
4,深入理解C++动态内存管理 malloc/free和new/delete的区别: a,他们都是动态内存管理的入口; b,malloc/free是C/C++标准库的函数,new/delete是C++操作符;
c,malloc/free只是动态分配内存/释放内存,而对于自定义类型,new/delete除了分配空间还能调用构造函数和析构函数进行初始化与清理。
d,malloc//free需要手动计算类型大小且返回值为void* ,new/delete可自己计算类型的大小,返回对应类型的指针。
5,C++的其他内存管理接口 void* operator new(size_t size); void* operator delete(size_t size); void* operator new[](size_t size); void* operator deletot[](size_t size);
注:以上不是运算符的重载。。。实际上只是malloc/free的一层封装,用法没变,他们只负责分配空间/释放空间,不会调用构造函数/析构函数来进行初始化或清理对象。
6,new 做了两件事:1,调用operator new分配空间;2,调用构造函数初始化对象
new[N]做了两件事:1,调用operator new;2,调用N次构造函数分别初始化每个对象。
7,定位new表达式 这是在已分配的原始内存空间中调用构造函数初始化一个对象。 new(place_address)type;
new(place_address)type(initializer_list);
例子:int main() { A* pa = (A*)operator new(sizeof(A)); new(pa) A(20); //delete pa; //等同于下面两步 pa->~A(); operator delete(pa); system("pause"); return 0; }