您的位置:首页 > 编程语言 > C语言/C++

C++第三节:二次删除、内存泄漏

2015-07-28 15:58 267 查看
类和对象的使用、二次删除、内存泄漏

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++ 课程