【C++学习笔记】14_动态内存分配
2014-07-07 13:37
260 查看
动态内存分配
在前面的程序中,将指针初始化为变量的地址(或用变量的地址来对指针变量赋值),此外,C++允许程序员利用专门的运算符“创建(new)”和“撤销(delete)”对内存进行动态分配,这样便可在程序运行时申请一块未命名的内存用来存储变量或者更为复杂的数据结构,并把该内存的首地址记录下来,以备将来访问。
【使用new动态分配内存】
new是一个单目运算符,操作数为一个类型名,返回值为指向操作数类型的指针。为一个变量分配动态的内存的基本格式为:
类型名*指针变量名= new类型名;
其中的“new 类型名”通知编译器:需要开辟的内存是用来存储的值是什么类型,new操作符能根据这个类型名自动计算要分配的存储空间的大小。
int *pNum= new int;
举例来说,上述代码会在运行时为一个int型数值分配内存,声明了指向int型的指针pNum,pNum初始为可以用动态申请内存的首地址,因此,用指针pNum可访问这块内存区域。
申请内存的同时可对该区域进行初始化,对基本的变量类型,下列语句是合法的:
int*pNum= newint(8);
动态申请了大小为int型的内存,将这块区域初始化为8,把该区域的首地址赋值给pNum。
【使用delete动态释放动态申请的内存】
动态申请的内存,在使用完毕后,应及时将其归还系统,以供其他程序使用,这项工作必须由程序员来完成,delete语句的使用格式是:
delete
指针;
其中的指针指向使用new动态申请的内存块,delete指令会释放动态申请的内存块,但不会删除指针本身,还可以将指针重新指向另一块内存区域。
delete语句不能释放声明变量获得的内存,如下述语句是错误的。
intx=3;
int* p=&x;
delete p; //错误
【使用new申请动态数组】
之前讨论了通过声明建立数组的方法,实际上,可以通过new[ ]命令动态创建数组,其基本格式为:
类型名*指针变量名= new类型名[元素个数];
上述语句通知编译器动态开辟足以存储“元素个数”个类型为“类型名”的元素的连续内存空间(数组),并声明“指针变量名”,指向数组的第一个元素。
和通过声明建立数组不同,使用new申请动态数组时,元素个数可以是变量,如:
inti=5
int* p=newint[ i ];//合法
这样,便可以在程序运行时决定应给数组分配的空间大小,而使用声明建立数组时,为了避免数组越界,一般都将数组的维数尽量设大一点,造成了内存的浪费,使用new申请动态申请数组可以克服这一弊端。
注意:
New无法对动态申请的数组存储区进行初始化。
对于动态申请的数组,在使用完毕之后,应使用“delete[]”命令将内存释放,其基本格式为:
delete[] 指针;
方括号告诉程序,应释放整个数组,而不仅仅是指针指向的元素,因此,一定要注意new和delete的配对,“new&delete”用于一个实体分配内存,而“new[]&delete[]”用于为数组分配内存。
代码示例【图1】:
运行结果【图2】:
【不要使用或释放已经释放的内存块】
使用或释放已经释放了的内存块会带来意想不到的错误,在使用delete释放内存时,delete后的指针并不要求一定是用new命令赋值的那个指针,编译器关心的是内存块的地址,而不是用哪个指针来释放。
代码示例【图3】:
运行结果【图4】:
DeletepN2释放掉的内存块是pN1的内存地址,所以cout<<*pN1<<endl;已经是没有意义了,所获得的结果并不是8,而是指针乱指的一个结果。
【使用malloc和free动态申请内存】
C++允许使用C标准库函数中的malloc()和free()函数申请和释放动态内存,保留这两个函数主要有以下几点考虑:
1)C++程序经常要调用写好的C函数,而在C语言中,只能使用malloc()和free()函数。
2)如果C++程序要运行在C语言环境下,必须使用malloc()和free()函数。
3)new和delete的功能是通过调用malloc()和free()来实现的。
注意:
malloc()和free()是C标准库函数,而new和delete是C++的运算符。
malloc()函数的基本调用格式为:
void *malloc( unsignedintsize );
举例来说,下列语句用于申请一段长度为len,数据类型为short的动态内存:
short* p=(short*)malloc(len* sizeof(short) );
由于malloc()函数返回值是void*,用返回值对其他类型指针赋值的时候,必须使用显性转换。同时malloc()函数是个无符号的整数,其仅仅关心申请字节的大小,并不管申请的内存块中存储的数据类型,因此,申请的内存长度需由程序员通过“长度xsizeof(类型)”的方式给出。
注意:
使用new和delete申请和释放动态内存的时候,内存的长度是由编译器自动计算的。
代码示例【图5】:
运行结果【图6】:
int的长度是4个字节,所以地址相差4,而且看得出是连续的,指针的运算:指针与整数的加减运算,表示指针在内存空间中向下或向上移动整数个单位,该单位是由指针所指变量的类型所决定的,比如,short型指针每次移动2个字节,double型指针每次移动8个字节。
代码中使用malloc()函数申请了一块可以存放5个int型数据的内存,并用for循环结构对5个数据分别进行赋值,在使用结束之后,不要忘记用free()函数释放申请的内存。
free()的基本格式如下:
void free(void* p);
其中,p就是指向所申请的内存块的指针。编译器可以完成由其他类型的指针指向void型指针的转换,因此直接使用“free(指针);”,就可以实现内存的释放,和之前介绍的一样,要避免使用或释放,已经释放了的内存。
注意:
如果指针为null,那么释放多少次都没有问题,因为它并不指向任何内存块。
【动态内存申请并不一定成功】
不论是使用标识符new、还是用malloc()函数,都不能保证一定能成功第申请到所需要的动态内存。一旦申请失败,但仍在后续代码中使用该块内存,程序就有崩掉的危险,因此,出于程序健壮性的考虑,在使用动态申请的内存块时,应首先判断申请是否成功(指针是否为null),如下面的代码所表示:
char*pC=new char[10];
if(pC!=null)
//执行操作
else
//内存申请失败处理
free()和delete()一个指针后,该指针所指向的动态内存被释放,但指针的值并不发生变化,常称此时的指针为“野指针”。通常,在内存释放后,将指针赋值为null,这样便不会再次释放已经释放的内存,并且,通过“if(指针)!=null”也可以进行防错。
在前面的程序中,将指针初始化为变量的地址(或用变量的地址来对指针变量赋值),此外,C++允许程序员利用专门的运算符“创建(new)”和“撤销(delete)”对内存进行动态分配,这样便可在程序运行时申请一块未命名的内存用来存储变量或者更为复杂的数据结构,并把该内存的首地址记录下来,以备将来访问。
【使用new动态分配内存】
new是一个单目运算符,操作数为一个类型名,返回值为指向操作数类型的指针。为一个变量分配动态的内存的基本格式为:
类型名*指针变量名= new类型名;
其中的“new 类型名”通知编译器:需要开辟的内存是用来存储的值是什么类型,new操作符能根据这个类型名自动计算要分配的存储空间的大小。
int *pNum= new int;
举例来说,上述代码会在运行时为一个int型数值分配内存,声明了指向int型的指针pNum,pNum初始为可以用动态申请内存的首地址,因此,用指针pNum可访问这块内存区域。
申请内存的同时可对该区域进行初始化,对基本的变量类型,下列语句是合法的:
int*pNum= newint(8);
动态申请了大小为int型的内存,将这块区域初始化为8,把该区域的首地址赋值给pNum。
【使用delete动态释放动态申请的内存】
动态申请的内存,在使用完毕后,应及时将其归还系统,以供其他程序使用,这项工作必须由程序员来完成,delete语句的使用格式是:
delete
指针;
其中的指针指向使用new动态申请的内存块,delete指令会释放动态申请的内存块,但不会删除指针本身,还可以将指针重新指向另一块内存区域。
delete语句不能释放声明变量获得的内存,如下述语句是错误的。
intx=3;
int* p=&x;
delete p; //错误
【使用new申请动态数组】
之前讨论了通过声明建立数组的方法,实际上,可以通过new[ ]命令动态创建数组,其基本格式为:
类型名*指针变量名= new类型名[元素个数];
上述语句通知编译器动态开辟足以存储“元素个数”个类型为“类型名”的元素的连续内存空间(数组),并声明“指针变量名”,指向数组的第一个元素。
和通过声明建立数组不同,使用new申请动态数组时,元素个数可以是变量,如:
inti=5
int* p=newint[ i ];//合法
这样,便可以在程序运行时决定应给数组分配的空间大小,而使用声明建立数组时,为了避免数组越界,一般都将数组的维数尽量设大一点,造成了内存的浪费,使用new申请动态申请数组可以克服这一弊端。
注意:
New无法对动态申请的数组存储区进行初始化。
对于动态申请的数组,在使用完毕之后,应使用“delete[]”命令将内存释放,其基本格式为:
delete[] 指针;
方括号告诉程序,应释放整个数组,而不仅仅是指针指向的元素,因此,一定要注意new和delete的配对,“new&delete”用于一个实体分配内存,而“new[]&delete[]”用于为数组分配内存。
代码示例【图1】:
运行结果【图2】:
【不要使用或释放已经释放的内存块】
使用或释放已经释放了的内存块会带来意想不到的错误,在使用delete释放内存时,delete后的指针并不要求一定是用new命令赋值的那个指针,编译器关心的是内存块的地址,而不是用哪个指针来释放。
代码示例【图3】:
运行结果【图4】:
DeletepN2释放掉的内存块是pN1的内存地址,所以cout<<*pN1<<endl;已经是没有意义了,所获得的结果并不是8,而是指针乱指的一个结果。
【使用malloc和free动态申请内存】
C++允许使用C标准库函数中的malloc()和free()函数申请和释放动态内存,保留这两个函数主要有以下几点考虑:
1)C++程序经常要调用写好的C函数,而在C语言中,只能使用malloc()和free()函数。
2)如果C++程序要运行在C语言环境下,必须使用malloc()和free()函数。
3)new和delete的功能是通过调用malloc()和free()来实现的。
注意:
malloc()和free()是C标准库函数,而new和delete是C++的运算符。
malloc()函数的基本调用格式为:
void *malloc( unsignedintsize );
举例来说,下列语句用于申请一段长度为len,数据类型为short的动态内存:
short* p=(short*)malloc(len* sizeof(short) );
由于malloc()函数返回值是void*,用返回值对其他类型指针赋值的时候,必须使用显性转换。同时malloc()函数是个无符号的整数,其仅仅关心申请字节的大小,并不管申请的内存块中存储的数据类型,因此,申请的内存长度需由程序员通过“长度xsizeof(类型)”的方式给出。
注意:
使用new和delete申请和释放动态内存的时候,内存的长度是由编译器自动计算的。
代码示例【图5】:
运行结果【图6】:
int的长度是4个字节,所以地址相差4,而且看得出是连续的,指针的运算:指针与整数的加减运算,表示指针在内存空间中向下或向上移动整数个单位,该单位是由指针所指变量的类型所决定的,比如,short型指针每次移动2个字节,double型指针每次移动8个字节。
代码中使用malloc()函数申请了一块可以存放5个int型数据的内存,并用for循环结构对5个数据分别进行赋值,在使用结束之后,不要忘记用free()函数释放申请的内存。
free()的基本格式如下:
void free(void* p);
其中,p就是指向所申请的内存块的指针。编译器可以完成由其他类型的指针指向void型指针的转换,因此直接使用“free(指针);”,就可以实现内存的释放,和之前介绍的一样,要避免使用或释放,已经释放了的内存。
注意:
如果指针为null,那么释放多少次都没有问题,因为它并不指向任何内存块。
【动态内存申请并不一定成功】
不论是使用标识符new、还是用malloc()函数,都不能保证一定能成功第申请到所需要的动态内存。一旦申请失败,但仍在后续代码中使用该块内存,程序就有崩掉的危险,因此,出于程序健壮性的考虑,在使用动态申请的内存块时,应首先判断申请是否成功(指针是否为null),如下面的代码所表示:
char*pC=new char[10];
if(pC!=null)
//执行操作
else
//内存申请失败处理
free()和delete()一个指针后,该指针所指向的动态内存被释放,但指针的值并不发生变化,常称此时的指针为“野指针”。通常,在内存释放后,将指针赋值为null,这样便不会再次释放已经释放的内存,并且,通过“if(指针)!=null”也可以进行防错。
相关文章推荐
- C++学习笔记14,private/protected/public继承,私有继承,保护继承,公有继承(五)(总结)
- C/C++学习笔记14:传递动态内存(2)
- C++ 学习笔记(14)重载运算与类型转换、函数对象、function库
- C++学习笔记14,private/protected/public继承,私有继承,保护继承,公有继承(五)(总结)
- [C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good
- 【C++】学习笔记草稿版14(继承与派生)
- C++学习笔记14 操作符的重载
- C++基础学习笔记:类与动态内存分配
- C++学习笔记14——默认实参
- Effective C++ 学习笔记(14)
- C++学习笔记14,private/protected/public继承,私有继承,保护继承,公有继承(五)(总结)
- C++学习笔记14 V-Tables && 虚继承
- C++学习笔记14: 抽象基类
- C++学习笔记--动态内存分配
- C++ FAQ学习笔记 14 章 友元
- Effective C++ 学习笔记14
- C++学习笔记(第12章->类和动态内存分配)
- c++学习笔记(14.函数模板)
- C++学习笔记3---类和动态内存分配
- c++入门学习笔记继承