1 以日期类为例
日期类的代码如下(只包含4个默认成员函数,为了便于观察结果所以在4个成员函数里面输出一些语句):
class Date
{
public:
Date()
{
cout << "Date()" << endl;
}
Date(const Date& d)
{
cout << "Date(const Date& d)" << endl;
}
Date& operator =(const Date& d)
{
cout << "Date& operator=(const Date& d)" << endl;
return *this;
}
~Date()
{
cout << "~Date()" << endl;
}
};
2 函数传参时
Date对象作为参数,此时不考虑返回值的问题,函数的返回值为void
2.1 Date对象作为参数采用传值方式
1.函数代码如下:
void fun1(Date d)
{}
2.函数调用的场景:
①创建对象与函数调用不在同一行
int main()
{
Date d1;
fun1(d1);
system("pause");
return 0;
}
分析
在main函数里面首先会创建一个对象d1,则会调用一次构造函数;接下来调用fun1函数时,由于fun1是值传递,所以会调用拷贝构造函数将d1拷贝构造给d。当出了fun1函数作用域后,会调用析构函数清理掉d;当fun1函数调用结束后,发现d1也没有再使用,也会调用d1的析构函数。综上:会调用一次构造,一次拷贝构造及两次析构函数。但是调用d1的析构函数只有在main函数快结束时,按F11可以进入Date的析构函数,此时无法输出到显示屏上。验证(运行结果如下)
②创建对象与函数调用在同一行(此时编译器会进行优化)
说明:因为我们有时候只是想调用一下某个函数,所以可以创建匿名对象,这里创建的对象为匿名对象Date(),匿名对象的作用域只在当前一行。
fun1(Date());
- 分析:
首先会创建一个Date的匿名对象,调用fun1时,会用这个匿名对象去拷贝构造一个d对象,编译器则会优化,会将两个步骤合二为一,则只会构造一个对象,所以只会调用一次构造函数,也只会调用一次析构函数。 - 验证: