析构函数:
析构函数同样也是特殊的成员函数,首先它的功能是和构造函数相反的,但他不是去销毁对象,对象销毁的工作是由编译器去做的,析构函数是去完成资源的清理工作,在对象销毁的时候自动调用
析构函数的特性:
- 函数名是在类名前面加上 ‘~’
- 无参数且无返回值
- 一个类有且只有一个析构函数,如果没有显示定义编译器会自动生成
- 一个对象生命周期结束,自动调用析构函数
大家看我下面的代码:我定义的对象里面的那三个成员变量会用到默认生成的析构函数嘛
class stu { public: stu(int a = 10,char c = 'A',int b = 20) { _a = a; _c = c; _b = b; } void print() { cout << _a << "-" << _c << "-" << _b << endl; } private: int _a; char _c; int _b; }; int main() { stu s1; }
这三个成员变量是不是我们的对象销毁的时候,它会自动的销毁啊,那我析构函数是去完成资源的清理的,那是不是malloc 那几个函数 还有new 以及fopen 这些才是析构函数要处理的阿,
注意:我们编译器默认生成的析构函数对malloc那些函数开辟的空间是不会自动去释放的,这些是需要我们自己手动去写的,这也是因为它无法判断一个指针到底是不是一块内存空间的地址,默认生成的析构函数对于内置类型不做处理,自定义类型调用它的析构函数:
class stu { public: stu(int a = 10,char c = 'A',int b = 20) { _a = a; _c = c; _b = b; } void print() { cout << _a << "-" << _c << "-" << _b << endl; } private: int _a; char _c; int _b; }; int main() { stu s1(20,'B',30); stu s2(40,'C',50); }
大家觉得这里的 s1和s2 谁先析构呢?
当然是s2会先析构 ,记得:析构顺序和构造的顺序是相反的
拷贝构造函数:
这个也是一个特殊的构造函数,它是构造函数的一种重载,它是拿一个已经定义好的对象去定义另外一个对象,同样他也是默认成员函数的一名,不写编译器自动生成:
对于内置类型(指针也是)会完成值(浅)拷贝,自定义类型会去调用它的拷贝构造(自己写的也会调用,哪怕你的函数里面没有写它的拷贝)
class stu { public: stu(stu& d) { _a = d._a; _c = d._c; _b = d._b; } stu(int a = 10,char c = 'A',int b = 20) { _a = a; _c = c; _b = b; } void print() { cout << _a << "-" << _c << "-" << _b << endl; } private: int _a; char _c; int _b; }; int main() { stu s1(20,'B',30); stu s2(s1);//s2 s3都是调用的拷贝构造函数 stu s3 = s2; }
注意:拷贝构造函数的参数只有一个并且必须使用引用传参,如果是传值传参会发生无限递归
对于那写内置类型的拷贝,都是按字节直接拷贝过去的,对于自定义类型,拷贝初始化规定要调用拷贝构造函数,至于其中的原因就涉及深浅拷贝的问题,就好像我malloc的空间的指针,如果直接赋值(浅拷贝),我两个对象的指针都指向的是同一块空间,那我在调用析构函数的时候,同一块空间被释放两次不就出问题了嘛,我们就得自己去实现拷贝构造
如果我们拷贝的成员里面又数组会报错嘛? :答案是不会的,我们数组拷贝又不是把数组的地址拷贝过去,拷贝的是数组里面的内容
我们的拷贝构造函数同样也是构造函数,他是我们平常写的构造函数的一种重载,我们如果类里面写了拷贝构造函数,那么编译器默认生成的构造函数就不会生成了!
还有一个问题就是涉及const的问题,通常我们在写的时候,如果自己写错了,写成了对 d对象 的成员变量赋值,那不就出错了嘛,所以我们要在拷贝构造的参数用const修饰一下,其实像这样我们不会改变的对象,加上const是最好的
class stu { public: stu(const stu& d) { _a = d._a; _c = d._c; _b = d._b; } stu(int a = 10,char c = 'A',int b = 20) { _a = a; _c = c; _b = b; } void print() { cout << _a << "-" << _c << "-" << _b << endl; } private: int _a; char _c; int _b; }; int main() { stu s1(20,'B',30); stu s2(s1);//s2 s3都是调用的拷贝构造函数 stu s3 = s2; }