关于构造函数,复制构造,和析构的问题。
类的复制构造函数有两种调用的类型,一种是显示的调用 例如 class A = B, 另外一种是隐式的调用,例如传递形参,或者函数返回时。
今天发现自己对以类类型作为形参使用时的构造和析构认识不够,所以又找了找资料,写了个验证程序来熟悉了一下。
有三种情况下需要调用复制构造函数:
1) 一个对象以值传递的方式传入函数体;
2) 一个对象以值传递的方式从函数返回;
3) 一个对象需要通过另外一个对象进行初始化;
按理说,一个调用过程中,类需要先构造,这里的构造包括普通构造和复制构造两类,然后生命周期结束后需要进行析构。
如下程序:
#include <iostream>
class Test {
public:
Test()
{
std::cout<< "调用无参数类型的构造函数!!\n" << std::endl ;
data = 0 ;
}
Test( int num )
{
data = num ;
std::cout << "调用有参数的构造函数!!\t 参数为:\t" << num << std::endl ;
}
~Test()
{
std::cout << "调用类的析构函数!!!\n" << std::endl;
}
Test(const Test & a )
{
this->data = a.data ;
std::cout << "调用复制构造函数!!\n" <<std::endl;
}
private:
int data;
};
// 测试按值传递的函数
Test passValue( Test b )
{
return b ;
}
//测试按引用传递的函数
Test passReference(Test & b)
{
return b ;
}
以上写了一个简单的类,包括两个函数,一个passValue用于测试按值传递过程中,类的构造和析构过程,另外一个passReference用于测试传递引用时,类的构造和析构过程 。
第一个测试main函数如下:
int main()
{
Test t1 = passValue(1) ;
Test t2 = passValue(t1) ;
return 0 ;
}
函数输出结果:
调用有参数的构造函数!! 参数为: 1
调用复制构造函数!!
调用类的析构函数!!!
调用复制构造函数!!
调用复制构造函数!!
调用类的析构函数!!!
调用类的析构函数!!!
调用类的析构函数!!
一共调用了一次带参数的构造函数,三次复制构造函数,和四次析构函数
调用的过程如下:
Test t1 = passValue(1) 语句中包括一次带形参的构造,一次复制构造,一次析构
1,首先隐式的调用带参数的构造函数Test(1) 成为一个临时Test类,记为temp1,(单个参数的构造函数这里有一个隐式的转换调用过程)
2,调用复制构造函数,将temp1复制给t1。
3,析构temp1,调用第一次析构函数来析构temp1,这点是我之前忽略的。
Test t2 = passValue(t1) 语句中包括两次复制构造函数,和一次析构函数
4, 调用复制构造函数对passValue()函数中的形参"t1"进行复制构造
5, 调用复制构造函数对t2进行复制构造。
6, 调用析构函数,析构形参“t1”
7, 调用析构函数,析构t2, // 因为t1和t2是在栈上分配的,所以析构过程先析构t2,然后析构t1
8, 调用析构函数,析构t1,
------------------------------------------------------------------------------------------------------------------
使用第二个测试函数进行测试
int main()
{
Test t1;
Test t2 = passReference(t1) ;
return 0 ;
}
输出如下:
调用无参数类型的构造函数!!
调用复制构造函数!!
调用类的析构函数!!!
调用类的析构函数!!!
此次调用调用了一次无参数的构造函数,一次复制构造,然后两次析构
Test t1; 中调用了一次无参的构造函数
Test t2 = passReference(t1) ; 中调用了一次复制构造函数,
其中因为passReference(t1) 传递的的为引用,所以不生成形参临时变量,少了一次构造和一次析构。
最后调用两次析构函数,分别析构 t2 和 t1 ;
另外 引用本身不是数据类型,只是某个目标变量的别名,所以使用passReference(1)是肯定不行的。