c++之堆的使用
来源:互联网 发布:mac 隐藏桌面磁盘 编辑:程序博客网 时间:2024/04/29 00:27
定义一个指针指向堆中的空间,指针所指向的空间是匿名的,只能通过该指针才能进行访问。用new关键字申请的匿名空间,必须用delete关键字进行删除。
一、在堆中创建内存
堆中用new创建的内存在程序结束时不会自动释放,通过指针来访问堆中的数据,程序结束时指针被自动释放,所以导致堆中的内存空间无法使用,也无法找到。这就是内存泄漏;所以尽量使用delete手动释放堆空间
#include<iostream>using namespace std;int main(){ int *p; p=new int;///堆,p指向创建的堆内存区域,大小与类型有关 *p=16; cout<<"*p:"<<*p<<endl; cout<<"p:"<<p<<endl; delete p; cout<<"释放堆中空间后*p的值:"<<*p<<endl; cout<<"重新定义指针p的指向"<<endl; p=new int; *p=8; cout<<"*p"<<*p<<endl; cout<<"p:"<<p<<endl; return 0;}
堆中指针只能通过delete释放,并且这种释放只是释放了指针先前指向的那段内存空间,使得这段内存空间可以用来存放其他值。指针并没有被删除,这时的指针是一个指向不确定的指针,使用指针之后要将其置0,表示为空指针,此时所指向的地址是0,该地址不能内容不可访问。在栈中使用指针则不必考虑这个问题,因为栈中的指针会被系统自动释放,只有用new时才使用delete。
在如下例子中,当指针p所指向的堆中内存被delete后,指针p保存的内存地址并没有改变,但是被释放的那段内存被系统用来存放了其他值;新定义的指针p1恰巧指向指针p释放的空间。但当改变指针p指向的值时,指针p1所指向的值也随之改变。说明指针p还是能对先前释放的内存进行操作。因此,在delelte一段内存之后,最好不要再使用它,或者将此指针赋值为0。
#include<iostream>using namespace std;int main(){ int *p=new int; *p=999; cout<<"删除p之前指向的内存地址为:"<<p<<ends<<"*p的值为:"<<*p<<endl; delete p; cout<<"删除p之后指向的内存地址为:"<<p<<ends<<"*p的值为:"<<*p<<endl; long *p1=new long; *p1=99999; cout<<"p1指向的内存地址为:"<<p1<<ends<<"*p1的值为:"<<*p1<<endl; *p=23; delete p; cout<<"p所指向的值改变之后,此时p1的值为:"<<*p1<<endl; cout<<"p本身的地址为:"<<&p<<endl; cout<<"p1本身的地址为:"<<&p1<<endl; return 0;}
二、在堆中创建对象
1.未使用delete释放堆中对象
class A{public: A(){cout<<"构造函数执行中"<<endl;x=999;} ~A(){cout<<"析构函数执行中"<<endl;}private: int x;};int main(){ A *p=new A;//在堆中创建匿名对象,只能通过指针访问该对象。并且在程序结束时,需要用delete手动释放堆中的对象。 return 0;//程序并没有调用析构函数}2.使用delete释放堆中对象
class A{public: A(){cout<<"构造函数执行中"<<endl;x=999;} ~A(){cout<<"析构函数执行中"<<endl;}private: int x;};int main(){ A *p=new A; delete p;//delete调用析构函数,释放堆中的对象 return 0;}
3.访问堆中的数据:堆采用匿名方式保存数据,只有通过指针才可以访问到数据,安全性高。堆中的空间不会自动释放,只有通过程序员来释放,属于动态内存;堆与栈不同,栈是系统自动分配内存,堆需要程序员通过new关键字来分配内存,栈是一段连续的内存空间,它的大小最多2M,而堆的内存空间不连续,由链表链接起来
class A{public: A(){cout<<"构造函数执行中"<<endl;x=999;} ~A(){cout<<"析构函数执行中"<<endl;} int getx(){return x;}private: int x;};int main(){ A *p=new A; cout<<(*p).getx()<<endl; delete p; return 0;}
4.在构造函数中开辟堆空间:在类的数据成员中,定义了一个指针类型的数据成员,并在构造函数中为指针成员申请堆中的空间。在程序结束时,系统自动调用析构函数析构对象,但是对象的数据成员在堆中的空间并未被释放,所以要在析构函数中加上delete i,这样才能在析构对象的时候释放指针i指向的堆中空间。
class A{public: A(){cout<<"构造函数执行中"<<endl;i=new int(999);} ~A(){cout<<"析构函数执行中"<<endl;delete i;} int getx(){return *i;}private: int *i;};int main(){ A *p=new A; cout<<(*p).getx()<<endl; delete p; return 0;}三、使用指针常见的错误
前面说过,在堆中删除一个指针后,一定要将该指针设置为空指针,这是因为删除该指针只会释放它所指向的内存空间,不会删除指针,因此这个指针还存在,并且仍然指向原来的空间。这时如果再次尝试使用该指针,就会出现错误。
在下例中,虽然指针p的对象被释放,但是p中保存的地址不变,使用p还是能改变该地址中对象的数据成员。
#include<iostream>using namespace std;class A{public: A(){i=100;cout<<"构造函数执行中..."<<endl;} ~A(){cout<<"析构函数执行中..."<<endl;} int get(){return i;} void set(int x){i=x;}private: int i;};int main(){ A *p=new A; cout<<(*p).get()<<endl; cout<<p<<endl; delete p; cout<<"删除P之后:"<<endl; cout<<(*p).get()<<endl; cout<<p<<endl; A *a=new A; //a与p指向同一个内存地址 cout<<(*a).get()<<endl; cout<<a<<endl; (*p).set(200);//p改变了对象的数据成员 cout<<(*a).get(); return 0;}其实用delete命令处理某个指针,说是把那个指针删除了是不正确的。delete命令指示释放了那个指针原本所指的那部分内存而已。被delete后的指针p的值(地址值)并非就是NULL,而是随机值。也就是被delete后,如果不再加上一句p=NULL,p就成了“野指针”,在内存里乱指一通。如果在定义p的那个函数在delete了p后,没再调用p,就没什么问题,在这个函数结束后,p就会跟其它变量一样被消除。但若在那个函数里delete了p后,又没再给p赋值(地址值),再次调用p就危险了,因为这时p在内存里乱指,有可能指到一些重要地址,随时可能系统崩溃。用delete删除一个指针后,这个指针还可以再次赋值使用。
#include <iostream>int main(){ int *p = new int; *p = 1; std::cout<<"p's adress is "<<p<<std::endl; delete p; if(p == NULL) { std::cout<<"p has changed"<<std::endl; } else { std::cout<<"p hasn't changed"<<std::endl; } std::cout<<"p's adress is "<<p<<std::endl; return 0;}
- c++之堆的使用
- STL之堆的使用
- C语言之栈和堆(Stack && Heap)的优缺点及其使用区别
- C++STL之堆
- 斜堆(一)之 C语言的实现
- 常见排序算法的C语言实现之堆排序
- 排序之堆排序的C语言实现
- C语言的堆
- [C++]数据结构:最大堆MaxHeap的创建与使用
- [C++]数据结构:最大堆MaxHeap的创建与使用
- c语言stack(栈)和heap(堆)的使用详解
- 最小堆&&最大堆的实现(c++)
- 最小堆&&最大堆的实现(c++)
- 最小堆&&最大堆的实现(c++)
- 堆的使用
- 堆的使用
- 堆的使用
- 堆的使用
- unity5 新布料系统 分析
- 杭电acm--2111
- 欢迎使用CSDN-markdown编辑器
- ios 中绘制图形
- Linux常用命令大全
- c++之堆的使用
- HDOJ 3635 Dragon Balls(并查集)
- 研究生期间ONE相关资料分享
- 悠闲的一天
- hdoj 4810 Wall Painting 【思维 + 组合数学】
- 每天的主题就是小小的积累
- 程序员怎样躲过降职
- WinPcap笔记(3):获取已安装设备的详细信息
- Extjs GridPanel 添加使用单选按钮radio