锁定老帖子 主题:析构函数 管理指针成员
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-02-23
析构函数就是这样的一个特殊函数,它可以完成所需的资源回收,作为类构造函数的补充撤销类对象 时会自动调用析构函数
动态分配的对象只有在指向该对象的指针被删除时才撤销
当对象的引用或指针超出作用域时,不会运行析构函数,只有删除指向动态分配对象的指针或实际对 象(而不是对象的引用)超出作用域时,才会运行析构函数
撤销一个容器(不管是标准库容器还是内置数组)时,也会运行容器中的类类型元素的析构函数
元素……直到最后撤销下标为 [0] 的元素
析构函数通常用于释放在构造函数或在对象生命期内获取的资源
常称为三法则,指的是如果需要析构函数,则需要所有这三个复制控制成员
析构函数并不仅限于用来释放资源,一般而言,析构函数可以执行任意操作,该操作是类设计者希望 在该类对象的使用完毕之后执行的
与复制构造函数或赋值操作符不同,编译器总是会为我们合成一个析构函数
合成析构函数按对象创建时的逆序撤销每个非 static 成员,因此,它按成员在类中声明次序的逆序 撤销成员,对于类类型的每个成员,合成析构函数调用该成员的析构函数来撤销对象
撤销内置类型成员或复合类型的成员没什么影响,尤其是,合成析构函数并不删除指针成员所指向的 对象
析构函数是个成员函数,它的名字是在类名字之前加上一个代字号(~),它没有返回值,没有形参 ,因为不能指定任何形参,所以不能重载析构函数,虽然可以为一个类定义多个构造函数,但只能提 供一个析构函数,应用于类的所有对象
析构函数与复制构造函数或赋值操作符之间的一个重要区别是,即使我们编写了自己的析构函数,合 成析构函数仍然运行
包含指针的类需要特别注意复制控制,原因是复制指针时只复制指针中的地址,而不会复制指针指向 的对象
大多数 C++ 类采用以下三种方法之一管理指针成员:
具有指针成员且使用默认合成复制构造函数的类具有普通指针的所有缺陷,尤其是,类本身无法避免 悬垂指针
建议:管理指针成员 必须保证成员所指向的对象存在,只要还有对象指向该对象
为了管理具有指针成员的类,必须定义三个复制控制成员:复制构造函数、赋值操作符和析构函数。 这些成员可以定义指针成员的指针型行为或值型行为
#include <iostream> #include <string> #include <vector> using namespace std; class Apple{ int i; public: Apple(int n):i(n){} ~Apple(){ cout << "Aapple No." << i << " destructed" << endl; } }; // class that has a pointer member that behaves like a plain pointer class HasPtr { public: // copy of the values we're given HasPtr(int *p, int i): ptr(p), val(i) { } // const members to return the value of the indicated data member int *get_ptr() const { return ptr; } int get_int() const { return val; } // non const members to change the indicated data member void set_ptr(int *p) { ptr = p; } void set_int(int i) { val = i; } // return or change the value pointed to, so ok for const objects int get_ptr_val() const { return *ptr; } void set_ptr_val(int val) const { *ptr = val; } private: int *ptr; int val; }; int main() { Apple a(0); // { // new scope Apple a1(1); } //exit local scope; destructor called on a1 Apple *a2 = 0; { a2 = new Apple(2); } //thouth exit local scope ,destructor not called cout << "Apple a2 still exist " << endl; delete a2; //ok destructor called on a2 cout << "===========================" << endl; Apple a3(3); Apple a4(4); Apple a5(5); { Apple as[3] = {a3,a4,a5}; } //destruct order: a5 a4 a3 int obj = 0; HasPtr ptr1(&obj, 42); // int* member points to obj, val is 42 HasPtr ptr2(ptr1); // int* member points to obj, val is 42 ptr1.set_int(0); // changes val member only in ptr1 cout << ptr2.get_int() << endl; // returns 42 cout << ptr1.get_int() << endl; // returns 0 ptr1.set_ptr_val(42); // sets object to which both ptr1 and ptr2 point cout << ptr2.get_ptr_val() << endl; // returns 42 int *ip = new int(42); // dynamically allocated int initialized to 42 HasPtr ptr(ip, 10); // Has Ptr points to same object as ip does delete ip; // object pointed to by ip is freed ptr.set_ptr_val(0); // disaster: The object to which Has Ptr points was freed! cout << ptr.get_ptr_val() << endl; int i = 42; HasPtr p1(&i, 42); HasPtr p2 = p1; cout << p2.get_ptr_val() << endl; p1.set_ptr_val(0); cout << p2.get_ptr_val() << endl; return 0; }
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 2894 次