- 浏览: 33791 次
- 性别:
- 来自: 南京
析构函数就是这样的一个特殊函数,它可以完成所需的资源回收,作为类构造函数的补充撤销类对象
时会自动调用析构函数
动态分配的对象只有在指向该对象的指针被删除时才撤销
当对象的引用或指针超出作用域时,不会运行析构函数,只有删除指向动态分配对象的指针或实际对
象(而不是对象的引用)超出作用域时,才会运行析构函数
撤销一个容器(不管是标准库容器还是内置数组)时,也会运行容器中的类类型元素的析构函数
容器中的元素总是按逆序撤销:首先撤销下标为 size() - 1 的元素,然后是下标为 size() - 2 的
元素……直到最后撤销下标为 [0] 的元素
析构函数通常用于释放在构造函数或在对象生命期内获取的资源
如果类需要析构函数,则它也需要赋值操作符和复制构造函数,这是一个有用的经验法则,这个规则
常称为三法则,指的是如果需要析构函数,则需要所有这三个复制控制成员
析构函数并不仅限于用来释放资源,一般而言,析构函数可以执行任意操作,该操作是类设计者希望
在该类对象的使用完毕之后执行的
与复制构造函数或赋值操作符不同,编译器总是会为我们合成一个析构函数
合成析构函数按对象创建时的逆序撤销每个非 static 成员,因此,它按成员在类中声明次序的逆序
撤销成员,对于类类型的每个成员,合成析构函数调用该成员的析构函数来撤销对象
撤销内置类型成员或复合类型的成员没什么影响,尤其是,合成析构函数并不删除指针成员所指向的
对象
析构函数是个成员函数,它的名字是在类名字之前加上一个代字号(~),它没有返回值,没有形参
,因为不能指定任何形参,所以不能重载析构函数,虽然可以为一个类定义多个构造函数,但只能提
供一个析构函数,应用于类的所有对象
析构函数与复制构造函数或赋值操作符之间的一个重要区别是,即使我们编写了自己的析构函数,合
成析构函数仍然运行
包含指针的类需要特别注意复制控制,原因是复制指针时只复制指针中的地址,而不会复制指针指向
的对象
大多数 C++ 类采用以下三种方法之一管理指针成员:
1. 指针成员采取常规指针型行为。这样的类具有指针的所有缺陷但无需特殊的复制控制
2. 类可以实现所谓的“智能指针”行为,指针所指向的对象是共享的,但类能够防止悬垂指针
3. 类采取值型行为,指针所指向的对象是唯一的,由每个类对象独立管理
具有指针成员且使用默认合成复制构造函数的类具有普通指针的所有缺陷,尤其是,类本身无法避免
悬垂指针
建议:管理指针成员
具有指针成员的对象一般需要定义复制控制成员,如果依赖合成版本,会给类的用户增加负担,用户
必须保证成员所指向的对象存在,只要还有对象指向该对象
为了管理具有指针成员的类,必须定义三个复制控制成员:复制构造函数、赋值操作符和析构函数。
这些成员可以定义指针成员的指针型行为或值型行为
#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; }
发表评论
-
复制构造函数
2008-02-19 00:36 5191只有单个形参,而且该形参是对本类类型对象的引用(常用 cons ... -
友元 static 类成员
2008-02-17 21:09 4479友元机制允许一个类将 ... -
名字查找 构造函数 explicit
2008-02-16 20:50 3927每个类都定义了自己的 ... -
成员函数 this指针 可变数据成员
2008-02-16 00:11 4112类的成员函数可以访问 ... -
类class(一)
2008-02-14 23:30 3516最简单地说,类就是定义了一个新的类型和一个新作用域每个类可以没 ... -
输入输出IO
2008-02-12 22:00 4163每一个 IO 头文件都定义了 char 和 wchar_t 类 ... -
函数function
2008-02-12 21:57 3380函数由函数名以及一组操作数类型唯一地表示。函数的操作数,也即形 ... -
语句(...)
2008-02-12 21:55 4152简单语句C++ 中,大多数 ... -
表达式
2008-02-12 21:52 3154表达式由一个或多个操 ... -
数组和指针
2008-02-12 21:48 5100数组是由类型名、标识符和维数组成的复合数据类型数组也是一种存储 ... -
标准库类型
2008-02-12 21:35 3017string 类型支持长度可变 ... -
变量和基本类型
2008-02-12 21:12 3888类型是所有程序的基础,类型告诉我们数据代表什么意思以及可以对数 ... -
Hello world续
2008-02-04 00:15 2842/*the first C++ program*/ #inc ... -
经典再现 Hello world
2008-02-03 01:54 3707语言:ANSI C++,即标准C++编译和运行环境:红旗 Re ...
相关推荐
但是如果一个类带了指针成员,那么需要我们自己来写一个析构函数来管理内存。在<<c>> 中写到,如果一个类需要我们自己写析构函数,那么这个类,也会需要我们自己写拷贝构造函数和拷贝赋值函数。 析构函数: 我们...
第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始化表 70 9.3 构造和析构的次序 72 9.4 示例:类String的构造函数与析构函数 72 9.5 不要轻视拷贝构造函数与赋值函数...
教程目录复制下面的链接打开后即可查看: ... 主要学习内容包含: 1、熟悉面向对象的语言概述 2、熟练掌握c++语言的基本知识和类与对象及其高级应用 ...12、虚函数、纯虚函数、抽象类、虚析构函数等
第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始化表 70 9.3 构造和析构的次序 72 9.4 示例:类STRING的构造函数与析构函数 72 9.5 不要轻视拷贝构造函数与赋值函数...
编程环境:win10,vs2017 #include 代码01 namespace ds01 { //类定义 struct DsSize { //没有明确写出构造和析构,编译器会使用默认构造、拷贝赋值、析构。 }; //测试程序 ...
将析构函数声明为虚函数。 (2)定义两个类Cat、Dog,都继承自Animal,并重载Identify函数,显示动物的种类及名字。 (3)定义一个Tiger类,继承自Cat,重载Identify函数,显示动物的种类和名字。 (4)定义一个...
第9章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源 9.2 构造函数的初始化表 9.3 构造和析构的次序 9.4 示例:类STRING的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数 9.6 示例:类...
智能指针主要思想是RAII思想,"使⽤对象管理资源",在类 的构造函数中获取资源,在类的析构函数中释放资源。智能指针的⾏为类似常规指针,重要的区别是它负责⾃动释放所指向的对象。 RAII是Resource Acquisition Is ...
第9章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源 9.2 构造函数的初始化表 9.3 构造和析构的次序 9.4 示例:类String的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数 9.6 示例...
第9 章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源 9.2 构造函数的初始化表 9.3 构造和析构的次序 9.4 示例:类STRING 的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数 9.6 示例:类...
第9章类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源 9.2 构造函数的初始化表 9.3 构造和析构的次序 9.4 示例:类String的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数 9.6 示例:类...
第9章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源 9.2 构造函数的初始化表 9.3 构造和析构的次序 9.4 示例:类String的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数 9.6 示例:类...
第9 章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源 9.2 构造函数的初始化表 9.3 构造和析构的次序 9.4 示例:类STRING 的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数 9.6 示例:类...
程序主要包含了类、指针、构造函数、析构函数、循环变量、分支结构、文件的建立以及读写等基本C++知识。通过这次程序设计不但提高了我们处理问题的能力,而且更深一步对C++语言的某些函数的正确的使用。
3、设计构造与析构函数,不要求输出信息,但各位同学可以自己输出并分析各个对象的创建与删除的情况: Book();//将m_ID初始化为0,表示这个一个未赋值对象 virtual ~Book();//无具体的工作 Book(const Book& other...
第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始化表 70 9.3 构造和析构的次序 72 9.4 示例:类STRING的构造函数与析构函数 72 9.5 不要轻视拷贝构造函数与赋值函数...
第9 章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源. 9.2 构造函数的初始化表. 9.3 构造和析构的次序. 9.4 示例:类STRING 的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数. ...
条款6:析构函数里对指针成员调用delete 条款7:预先准备好内存不够的情况 条款8: 写operator new和operator delete时要遵循常规 条款9: 避免隐藏标准形式的new 条款10: 如果写了operator new就要同时写operator ...
第9 章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源. 9.2 构造函数的初始化表. 9.3 构造和析构的次序. 9.4 示例:类STRING 的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数. 9.6 示例...
第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始化表 70 9.3 构造和析构的次序 72 9.4 示例:类String的构造函数与析构函数 72 9.5 不要轻视拷贝构造函数与赋值函数...