C++带有指针成员的类处理方式详解
|
副标题[/!--empirenews.page--]
在一个类中,如果类没有指针成员,一切方便,因为默认合成的析构函数会自动处理所有的内存。但是如果一个类带了指针成员,那么需要我们自己来写一个析构函数来管理内存。在<<c++ primer>> 中写到,如果一个类需要我们自己写析构函数,那么这个类,也会需要我们自己写拷贝构造函数和拷贝赋值函数。 析构函数: 我们这里定义一个类HasPtr,这个类中包含一个int 类型的指针。然后定义一个析构函数,这个函数打印一句话。 HasPtr.h 类的头文件
#pragma once
#ifndef __HASPTR__
#define __HASPTR__
class HasPtr
{
public:
HasPtr(int i,int *p);
//HasPtr& operator=(HasPtr&);
//HasPtr(const HasPtr&);
~HasPtr();
int get_ptr_value();
void set_ptr_value(int *p);
int get_val();
void set_val(int v);
private:
int val;
int *ptr;
};
#endif // !__HASPTR__
HasPtr.cpp 类的实现
#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;
HasPtr::HasPtr(int i,int *p)
{
val = i;
ptr = p;
}
int HasPtr::get_ptr_value()
{
return *ptr;
}
void HasPtr::set_ptr_value(int *p)
{
ptr = p;
}
int HasPtr::get_val()
{
return val;
}
void HasPtr::set_val(int v)
{
val = v;
}
HasPtr::~HasPtr()
{
cout << "destructor of HasPtr " << endl;
}
ClassWithPointer 类,包含main入口,HasPtr在stack上。
// ClassWithPointer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;
int main()
{
int temp = 100;
HasPtr ptr(2,&temp);
cout << ptr.get_ptr_value() << endl;
cout << ptr.get_val() << endl;
system("PAUSE");
system("PAUSE");
return 0;
}
执行该入口方法,发现最后还是打印了析构函数这句话,OK,在main 方法中,stack上定义了一个HasPtr,在main方法退出前,析构函数自动调用了。 如果将HasPtr改为动态对象,也就是放在堆上呢? ClassWithPointer 类,包含main入口,HasPtr在heap上。
// ClassWithPointer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;
int main()
{
int temp = 100;
//HasPtr ptr(2,&temp);
HasPtr *ptr = new HasPtr(2,&temp);
cout << ptr->get_ptr_value() << endl;
cout << ptr->get_val() << endl;
system("PAUSE");
return 0;
}
执行一下,发现析构函数没有调用。OK,我们在return 0前面添加一个delete ptr; 析构函数执行了。 所以,这里有两个结论:
现在在析构函数中调用delete 语句来删除指针成员。 头文件不变,HasPtr.cpp 文件代码如下:
#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;
HasPtr::HasPtr(int i,int *p)
{
val = i;
ptr = p;
}
int HasPtr::get_ptr_value()
{
return *ptr;
}
void HasPtr::set_ptr_value(int *p)
{
ptr = p;
}
int HasPtr::get_val()
{
return val;
}
void HasPtr::set_val(int v)
{
val = v;
}
HasPtr::~HasPtr()
{
cout << "destructor of HasPtr " << endl;
delete ptr;
}
ClassWithPointer 代码如下:
// ClassWithPointer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;
int main()
{
int temp = 100;
HasPtr ptr(2,&temp);
cout << ptr.get_ptr_value() << endl;
cout << ptr.get_val() << endl;
system("PAUSE");
return 0;
}
执行一下,正常打印结束后,抛出错误:
这里说明delete 不能删除stack 上的指针值。 现在在ClassWithPointer传入一个动态指针来测试一下。
// ClassWithPointer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;
int main()
{
int temp = 100;
HasPtr ptr(2,&temp);
cout << ptr.get_ptr_value() << endl;
cout << ptr.get_val() << endl;
system("PAUSE");
return 0;
}
执行后析构函数正常运行。所以这里有两个结论:
默认拷贝构造函数和默认赋值操作: 这里我们调用默认的构造函数和默认的赋值操作,看看会出现什么,为了方便查看,我在析构函数中打印了当前对象的地址,以及在main方法中打印了对象地址,这样就可以看到哪个对象调用了析构函数: HasPtr.cpp 代码如下:
#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;
HasPtr::HasPtr(int i,int *p)
{
val = i;
ptr = p;
}
int HasPtr::get_ptr_value()
{
return *ptr;
}
void HasPtr::set_ptr_value(int *p)
{
ptr = p;
}
int HasPtr::get_val()
{
return val;
}
void HasPtr::set_val(int v)
{
val = v;
}
HasPtr::~HasPtr()
{
cout << "destructor of HasPtr " << this << endl;
delete ptr;
}
(编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


