简单的写一个日期类,包含四个默认成员函数
注意
:调用构造函数的次数+调用拷贝构造的次数=析构的次数
本例中 有一个Date变量和main函数的生命周期是一样的,所以会少一次析构。
如果把测试用例封装到函数中,则调用析构的次数正确。
#pragma once
#include<iostream>
using namespace std;
class Date
{
public:
Date()
{
cout <<"构造函数" <<"Date()" << endl;
}
Date(const Date& x)
{
cout << "拷贝构造" << "Date(const Date& x)" << endl;
}
~Date()
{
cout << "析构函数" << "~Date()" << endl;
}
Date& operator= (const Date& x)
{
cout << "赋值运算符重载" << "Date& operator= (const Date& x)" << endl;
return *this;
}
};
测试用例
1.
void f1(Date d)
//void f1(Date& d)
//传引用减少拷贝构造
{
}
int main()
{
Date d1;//会调用一次构造
f1(d1);//传值时会调用一次拷贝构造
system("pause");
}
运行结果:
2.
Date f2()
//Date& f2()//返回引用减少一次拷贝构造
{
Date ret;//会调用一次构造函数
return ret;//返回值时会产生临时变量(一次拷贝),临时变量再返回(一次拷贝),编译器优化只会调用一次拷贝构造
}
int main()
{
f2();
system("pause");
}
运行结果:
3.
Date f3()
{
Date ret;//会调用一次构造
return ret;//返回值时会产生临时变量(一次拷贝),临时变量再返回(一次拷贝),编译器优化只会调用一次拷贝构造
}
int main()
{
Date d1 = f3();//上式所说的优化只能是在同一表达式中
system("pause");
}
运行结果:
4.
Date f4()
{
return Date();
//返回值时会产生临时变量(一次拷贝),紧接着Date()会调用一次构造,编译器优化成一次构造,临时变量再返回(一次拷贝)和一次构造优化成一次构造。
//对比测试用例3,测试用例3已经构造好了在返回的,所以会合并成一次拷贝构造
}
int main()
{
Date d1 = f4();
system("pause");
}
运行结果:
5.
void f5(Date d)
{
}
int main()
{
Date d5;//一次构造
f5(d5);//一次拷贝
system("pause");
}
运行结果:
6.
void f6(Date d)
{
}
int main()
{
f6(Date());//一次构造
system("pause");
}
运行结果:
总结
:
1.传引用会减少拷贝构造,如测试用例1和5
2.返回值时会优化(如测试用例2),返回值在一个表达式内也会优化(如测试用例3)
3.如果传值(如测试用例6)或者是返回值(如测试用例4)都是类类型,并且会调用构造函数,那么会优化为构造函数构造
经典面试题:
class AA
{
public:
AA()
{
cout <<"构造函数" <<"AA()" << endl;
}
AA(const AA& x)
{
cout << "拷贝构造" << "AA(const AA& x)" << endl;
}
~AA()
{
cout << "析构函数" << "~AA()" << endl;
}
AA& operator= (const AA& x)
{
cout << "赋值运算符重载" << "AA& operator= (const AA& x)" << endl;
return *this;
}
};
AA f(AA a)
{
return a;
}
void test1()
{
AA a1;
a1 = f(a1); //f(a1)传值会调用一次拷贝构造
//返回值时会产生临时变量(一次拷贝),临时变量再返回(一次赋值运算符的重载)
}
void test2()
{
AA a1;
AA a2 = f(a1); //f(a1)传值会调用一次拷贝构造
//返回值时会产生临时变量(一次拷贝),临时变量再返回(一次拷贝),编译器优化只会调用一次拷贝构造
}
void test3()
{
AA a1;
AA a2 = f(f(a1)); //f(a1)传值会调用一次拷贝构造
//f(a1)返回值时会产生临时变量(一次拷贝),临时变量再返回(一次拷贝),编译器优化只会调用一次拷贝构造
//f(f(a1))返回值时会产生临时变量(一次拷贝),临时变量再返回(一次拷贝),编译器优化只会调用一次拷贝构造
}
测试用例
int main()
{
//test1();
//test2();
test3();
system("pause");
}
test1运行结果:
test2运行结果:
test3运行结果: