C++第三节:二次删除、内存泄漏
2015-07-28 15:58
309 查看
类和对象的使用、二次删除、内存泄漏
1、类和对象的使用:
1.1 可以向一个函数传递对象作为参数,对象也可以作为函数的返回值,有传值、传指针、传引用三种方式
1.2 为了避免对象的拷贝,经常传递对象的引用,并使用const避免被修改(const & x)
1.3 如果传值方式返回,系统将创建一个临时对象,来接受返回值
1.4 可以把一个对象赋值给另外一个对象,对象每个成员的值,将一对一拷贝到新的对象,称为逻辑拷贝或浅拷贝
2、二次删除、内存泄漏
2.1 如果对象a,b含有指针成员变量,而指针变量又指向堆上空间,将只拷贝指针成员变量本身的值,造成两个对象的指针指向同一堆上的内存空间,删除对象时造成二次删除
2.2 二次删除中,如果对象a的指针成员变量原来指向堆上空间,将对象b赋值给a,则原来指向的堆上空间没有指针变量控制,造成内存泄漏
3、this指针
3.1 每个对象都隐式的包含了一个成员变量,this
3.2 this是一个指针,指向对象自己,其值是对象的地址
A、简单复合类
Computer2.h
Computer.h
C、二次删除、内存泄漏
Computer3.h
1、类和对象的使用:
1.1 可以向一个函数传递对象作为参数,对象也可以作为函数的返回值,有传值、传指针、传引用三种方式
1.2 为了避免对象的拷贝,经常传递对象的引用,并使用const避免被修改(const & x)
1.3 如果传值方式返回,系统将创建一个临时对象,来接受返回值
1.4 可以把一个对象赋值给另外一个对象,对象每个成员的值,将一对一拷贝到新的对象,称为逻辑拷贝或浅拷贝
2、二次删除、内存泄漏
2.1 如果对象a,b含有指针成员变量,而指针变量又指向堆上空间,将只拷贝指针成员变量本身的值,造成两个对象的指针指向同一堆上的内存空间,删除对象时造成二次删除
2.2 二次删除中,如果对象a的指针成员变量原来指向堆上空间,将对象b赋值给a,则原来指向的堆上空间没有指针变量控制,造成内存泄漏
3、this指针
3.1 每个对象都隐式的包含了一个成员变量,this
3.2 this是一个指针,指向对象自己,其值是对象的地址
A、简单复合类
Computer2.h
#ifndef __C__No728Class__Computer2__ #define __C__No728Class__Computer2__ #include <iostream> using namespace std; class Computer2 { private: int lines; double width; double height; public: Computer2(int l, double w, double h); ~Computer2(); void print(); }; #endif /* defined(__C__No728Class__Computer2__) */Computer2.cpp
#include "Computer2.h" Computer2::Computer2(int l, double w, double h) { lines = l; width = w; height = h; } void Computer2::print() { cout << "lines is " << lines << endl; cout << "width is " << width << endl; cout << "height is " << height << endl << endl; } Computer2::~Computer2() { cout << "析构computer2" << endl; }Room2.h
#ifndef __C__No728Class__Room2__ #define __C__No728Class__Room2__ #include <iostream> using namespace std; #include "Computer2.h" class Room2 { private: int num; Computer2 *c; public: Room2(int l, double w, double h, int n); ~Room2(); void print(); }; #endif /* defined(__C__No728Class__Room2__) */Room2.cpp
#include "Room2.h" Room2::Room2(int l, double w, double h, int n) { c = new Computer2(l, w, h); num = n; } void Room2::print() { (*c).print(); cout << "num is " << num << endl << endl; } Room2::~Room2() { cout << "析构Room2" << endl; if(c) { delete c; c = NULL; } }main.cpp
#include "Room2.h" int main () { Computer2 c1(5, 5, 5); c1.print(); Computer2 *c2; c2 = new Computer2(4, 4, 4); (*c2).print(); delete c2; //调用析构函数,析构Computer2(c2) c2 = NULL; Room2 r1(3, 3, 3, 3); r1.print(); Room2 *r2; r2 = new Room2(2, 2, 2, 2); r2->print(); delete r2; //调用析构函数,析构room2、析构Computer2(r2) r2 = NULL; return 0; //析构room2、析构Computer2(r1)、析构Computer2(c1) }B、指针复合类
Computer.h
#ifndef __C__No728Class__Computer__ #define __C__No728Class__Computer__ #include <iostream> using namespace std; class Computer { private: int * lines; double * width; double height; public: Computer(int *l, double *w, double h); ~Computer(); void print(); }; #endif /* defined(__C__No728Class__Computer__) */Computer.cpp
#include "Computer.h" Computer::Computer(int *l, double *w, double h) { lines = new int(*l); //指向堆空间 width = w; //指向栈空间 height = h; } void Computer::print() { cout << "lines is " << *lines << endl; cout << "width is " << *width << endl; cout << "height is " << height << endl; } Computer::~Computer() //析构函数,回收内存,手工收回堆空间 { cout << "析构Computer" << endl; if(lines) { delete lines; lines = NULL; } }Room.h
#ifndef __C__No728Class__Room__ #define __C__No728Class__Room__ #include <iostream> #include "Computer.h" class Room { private: int num; Computer *c; public: Room(int *l, double *w, double h, int n); ~Room(); void print(); }; #endif /* defined(__C__No728Class__Room__) */Room.cpp
#include "Room.h" Room::Room(int *l, double *w, double h, int n) { num = n; c = new Computer(l, w, h); //指向堆空间,里面是一个Computer的对象 } Room::~Room() { cout << "析构Room" << endl; if(c) { delete c; c = NULL; } } void Room::print() { (*c).print(); cout << "num is " << num << endl; }main.cpp
#include "Room.h" int main () { int a = 5; double b = 5; Computer c1(&a, &b, 5); c1.print(); a--;b--; Computer *c2; c2 = new Computer(&a, &b, 4); (*c2).print(); delete c2; //调用析构函数,析构Computer(c2) c2 = NULL; a--;b--; Room r1(&a, &b, 3, 3); r1.print(); a--;b--; Room *r2; r2 = new Room(&a, &b, 2, 2); r2->print(); delete r2; //调用析构函数,析构room、析构Computer(r2) r2 = NULL; return 0; //析构room、析构Computer(r1)、析构Computer(c1) }
C、二次删除、内存泄漏
Computer3.h
#ifndef __C__No728Class__Computer3__ #define __C__No728Class__Computer3__ #include <iostream> using namespace std; class Computer3 { private: int * lines; double * width; double height; public: Computer3(int *l, double *w, double h); ~Computer3(); void print(); }; #endif /* defined(__C__No728Class__Computer3__) */Computer3.cpp
#include "Computer3.h" Computer3::Computer3(int *l, double *w, double h) { lines = new int(*l); //指向堆空间,等价于lines = new int; *lines = *l; width = w; //指向栈空间 height = h; } void Computer3::print() { cout << "lines is " << *lines << endl; cout << "width is " << *width << endl; cout << "height is " << height << endl; } Computer3::~Computer3() //析构函数,回收内存,手工收回堆空间 { if(lines) { delete lines; lines = NULL; } cout << "析构Computer3" << endl; }Room3.h
#ifndef __C__No728Class__Room3__ #define __C__No728Class__Room3__ #include <iostream> #include "Computer3.h" class Room3 { private: int num; Computer3 *c; public: Room3(int *l, double *w, double h, int n); ~Room3(); void print(); }; #endif /* defined(__C__No728Class__Room3__) */Room3.cpp
#include "Room3.h" Room3::Room3(int *l, double *w, double h, int n) { num = n; c = new Computer3(l, w, h); //指向堆空间,里面是一个Computer的对象 } Room3::~Room3() { if(c) { delete c; c = NULL; } cout << "析构Room3" << endl; } void Room3::print() { (*c).print(); cout << "num is " << num << endl; }main.cpp
#include "Room3.h" int main () { int a = 5; double b = 5; Computer3 c1(&a, &b, 5); //Computer3 c3 = c1; //二次删除,c3的lines与c1的lines指向同一堆空间,回收c3,调用Computer3析构函数,有非空指针lines,delete lines 并置空,(c1的lines并没有被置空),同理,回收c1 //Computer3 c3(&a, &b, 5); //二次删除、内存泄漏 //c3 = c1; //c3重新赋值后,c3的lines与c1的lines指向同一堆空间,c3的lines原来指向的堆空间泄漏,回收c3,与上面情况相同 c1.print(); Computer3 *c2; c2 = new Computer3(&a, &b, 4); (*c2).print(); delete c2; //delete c2,即删除c2指向的堆空间,调用Computer3析构函数,此堆空间中有非空指针lines,需要删除l指向的堆空间并置空,析构Computer3(c2) c2 = NULL; a4b8 Room3 r1(&a, &b, 3, 3); //Room3 r3 = r1; //double 二次删除,r1的c和r3的c指向同一堆空间,系统先自动回收栈上空间r3,调用Room3析构函数,r3中有Computer3类类型指针c且非空,delete c,删除c指向的堆空间,即销毁Computer3的c对象,调用Computer3析构函数,该堆空间中(c对象)有非空指针lines,delete lines,删除lines指向的堆空间,r3回收完,然后同理,回收r1 //Room3 r3(&a, &b, 3, 3); //double二次泄漏,double二次删除 //r1 = r3; //r1重新赋值后,r1的c与r3的c指向同一堆空间,r1的c原来指向的堆空间及该堆空间中lines指向的堆空间泄漏,系统先自动回收栈上空间r3,与上面情况相同 r1.print(); Room3 *r2; r2 = new Room3(&a, &b, 2, 2); //delete r2,删除r2指向的堆空间,即需删除Room3的一个对象,调用Room3析构函数,该堆空间有非空指针c,delete c并置空,即删除c指向的堆空间,即需删除Computer3的一个对象,调用Computer析构函数,该堆空间有非空指针lines,delete lines 并置空,即删除lines指向的堆空间(*l),回收完成 r2->print(); delete r2; //调用析构函数,析构Computer3、析构room3(r2) r2 = NULL; return 0; //析构Computer3、析构room3(r1)、析构Computer3(c1) }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- C++ Custom Control控件向父窗体发送对应的消息
- C++中拷贝构造函数的应用详解