引子:
1、存储分配:
(1)通常定义变量(或对象),编译器在编译时都可以根据该变量(或对象)的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间。这种内存分配称为静态存储分配;
(2)有些操作对象只在程序运行时才能确定,这样编译时就无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配(堆中的内存空间),这种方法称为动态存储分配。
2、内存区域:
(1)全局代码区:从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2)堆内存(heap):亦称动态内存。如malloc和new申请的内存空间,要用指针访问,没有先后顺序。动态内存的生存期由程序员自己决定,需要手动释放内存,使用非常灵活。
(3)栈内存(stack):依附于线程,先进后出,存储局部数据。如存放函数的参数值、函数变量的值等,自动分配。生存期完结自动回收。
工作机制:(引自百度百科)
操作系统将可用的内存块连接为一个长长的列表的所谓空闲链表。
申请动态内存时,沿连接表寻找一个大到足以满足用户请求所需要的内存块。
然后,将该内存块一分为二(一块的大小与用户请求的大小相等,另一块的大小就是剩下的字节)。接下来,将分配给用户的那块内存传给用户,并将剩下的那块(如果有的话)返回到连接表上。
释放动态内存时,它将用户释放的内存块连接到空闲链上。
1、malloc函数
函数原型:void
*
malloc
(unsigned
int
num_bytes);
是什么:malloc的全称是memory allocation,中文叫动态内存分配。
干什么:
用于申请一块连续的指定大小的内存块区域,以void*类型返回分配的内存区域地址。
如果申请不成功,返回NULL。
其中,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针。
怎么用:
#include<iostream>
#include<stdlib.h> //包含malloc()函数的头文件,不可省略.h,这是一个C的头文件
using namespace std;
void main()
{
char *p=(char*)malloc(sizeof(char) * 5); //申请了5个连续的字符型空间,也就是5*1个byte。
if(p!=NULL) //如果无法获得符合要求的内存块,malloc函数会返回NULL指针,因此在调用malloc动态申请内存块时,一定要进行返回值的判断。)
{
......
}
else
{
printf("mallocerror!\n");
exit(-1);
}
free(p); //当内存不再使用时,用free()函数将此内存返还给系统
p=NULL;
}
使用注意:
(1)malloc函数要求必须要由我们计算字节数,作为参数传递给malloc函数。如上例中的参数sizeof(char)*5。
(2)在返回给某个指针时,由于malloc函数返回的是void*类型的指针,所以需要强制转换类型。如上例中的(char*)。 对于C++,如果你写成:
char *p=malloc(sizeof(char) * 5);
则程序无法通过编译,报错:“不能将 void* 赋值给 int * 类型变量”。
(3)malloc一般与free函数配对使用,否则易造成内存泄漏。
而且free函数调用以后,内存空间虽然已经归还,但是指针仍然指向原地址。
(4)malloc不会自动初始化内存空间,里面是随机值。
*calloc函数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
char *str;
/*分配内存空间*/
str = (char*)calloc(10,sizeof(char));
/*将hello写入*/
strcpy(str, "Hello");
/*显示变量内容*/
printf("String is %s\n",str);
/*释放空间*/
free(str);
}
2、new运算
是什么:是个封装好的运算符,不是函数,因此不需要库的支持。
干什么:用于申请堆中分配的存贮空间。
怎么用:
(1)指针变量名 = new 类型名(初始化式);(申请一个内存空间)
int *p=new int(5);//申请一个int空间,初始化为5
delete p;
(2)指针变量名 = new 类型名[个数];(申请一堆连续的动态内存空间)
int* p=new int[5];//申请5个连续的int型内存
delete []p;
使用注意:
(1)自动计算需要分配的空间,返回的是个指向所分配类型变量(对象)的指针。
(2)初始化规律:对于有构造函数的类,不论有没有括号,都用构造函数进行初始化;如果没有构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,而在末尾加了括号的new会在分配内存的同时初始化为0。
(3)delete通常与new配对使用。
delete p;释放了指针p所指的目标的内存空间,但指针p本身并没有撤销,它自己仍然存在,该指针仍然指向原地址。
(4)指针p存于栈中,p所指向的内存空间是在堆中。
(5)在c++中与malloc的最大区别:
2、malloc和free属于C语言中的函数,需要库的支持,而new/delete是C++中的运算符,所以new/delete的执行效率高些。C++中为了兼用C语法,所以保留malloc和free的使用,但建议尽量使用new和delete。
3、new类型安全,返回的是某种数据类型的指针,malloc非类型安全,返回的是void指针。
int* p = malloc(sizeof(char )*10); // 编译时无法指出错误
free (p); //只释放内存的头指针