构造函数是成员函数的一种
- 名字与类名相同,可以有参数,不能有返回值,void也不行。
- 作用的对对象进行初始化,给成员变量赋初值
- 如果定义是没写构造函数,则编译器默认生成一个无参的构造函数(默认生成的构造函数无参数,不做任何操作)
- 对象生成时,构造函数自动被调用,对象一旦生成,就再也不能在其上执行构造函数
- 一个类可以有多个构造函数
构造函数执行必要的初始化工作,有了构造函数就不必在专门写初始化函数,也不用调用
复制构造函数
只有一个参数,即对同类对象的引用
形如X::X(X&)或者X::X(const x &) 二者选一 后者能以常量对象作为参数
如果没有定义辅助构造函数,那么编译器生成默认构造函数,默认的复制构造函数完成复制功能
对比:
无参构造函数(构造函数)它不一定存在,只有你不写构造函数时,编译器才会帮你生成构造函数,而你写了时编译器不会生成
而复制构造函数一定存在,你不写编译器就帮你写
对于复制构造函数来说,不允许出现X::X(X)的构造函数,因为复制构造函数的参数必须是引用,不能是对象
复制构造函数起作用的情况
- 当用一个对象初始化同类的另一个对象时;
Complex c1; Complex c2(c1); 等价于 Complex c1=c2;(这不是赋值语句,这是初始化语句)
- 一个函数的参数如果是对象的话,就一定调用的是复制构造函数,这是C++的规定
- 如果一个函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用
注意:对象间的赋值并不导致复制构造函数被调用
常量引用参数的使用
void func(Myclass obj){cout<<"fun"<<endl;}
- 这样的函数调用时开销比较大,因为会引发复制函数的调用
- 可以考虑使用Myclass&类型作为参数
- 如果希望确保实参的值在函数中不应被改变,也可以加上const关键字
类型转换构造函数
定义
- 定义转换构造函数的目的是实现类型的自动转换
- 只有一个参数,而且不是复制构造函数的构造函数,一般就可以看作是转换构造函数(特殊的构造函数)
- 当需要的时候,编译系统就会自动调用转换构造函数,建立一个无名的临时对象
析构函数
- 名字与类名相同,在前面加‘~',没有参数和返回值,一个类最多只有一个析构函数
- 析构函数在对象消亡时即自动被调用,可以定义析构函数来在对象消亡前后做善后工作,比如释放分配的空间
- 如果定义时,没写析构函数,可以默认编译器自动生成一个缺省的析构函数,可以默认为缺省的析构函数什么也不做
- 如果定义了析构函数,则编译器不在生成
对象数组生命周期结束时,对象数组的每个元素的析构函数都会被调用
delete的运算导致析构函数的调用,如果不用delete,那么这个对象不会凋亡,也不会引发析构函数的调用
析构函数在对象作为函数的返回值返回后也会被调用
构造函数和析构函数容易误解的地方
- 构造函数,构造函数只负责初始化,空间已经有了,(构造函数不造房子,只是负责装修)
- 析构函数,并不负责回收整个对象所占的存储空间,只是在对象的存储空间被回收之前做一些善后工作(不负责房子的拆迁,只是负责一些善后工作,在被拆掉之前,搬走一些东西)
复制构造函数在不同编译器的表现也不一样