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; } (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |