构造函数拷贝赋值函数的N种调用情况

1.C++对传参合传返回值时构造的优化处理
#include<iostream>
usingnamespacestd;
classDate
{
public:
    Date(intyear = 1990,intmonth = 1,intday = 1)
    {
    }
    Date(constDate& d)
    {
         cout<<"Date(const Date& d)"<<endl;
    }
    ~Date()
    {
         cout<<"~Date()"<<endl;
    }
private:
    int_year;
    int_month;
    int_day;
};
(1)Date对象做参数传值
voidFunc1(Date d)
{
}
intmain()
{
    Date d1;
    Func1(d1);
    return0;
}
输出结果为:
构造函数拷贝赋值函数的N种调用情况



(2)Date对象做参数传引用
voidFunc1(Date& d)
{
    
}
intmain()
{
    Date d1;
    Func1(d1);
    return0;
}
输出结果为:
构造函数拷贝赋值函数的N种调用情况


通过(1)(2),我们可以看出传引用可以不调用拷贝构造函数

(3)Date对象做返回值传值
Date Func2()
{
    Date d;
    returnd;
}
intmain()
{
    Date d1;
    Func2();
    return0;
}

输出结果为:
构造函数拷贝赋值函数的N种调用情况

(4)Date对象做返回值传引用
Date& Func2()
{
    Date d;
    returnd;
}
intmain()
{
    Date d1;
    Func2();
    return0;
}
输出结果为:
构造函数拷贝赋值函数的N种调用情况


通过(3)(4)比较可以看出,当传引用返回时,则不调用构造函数。
但要注意的一点则是:不要返回一个临时变量的引用!

(5)编译器优化问题
i.Date对象做临时返回值传引用(不能使用引用!
Date& Func3()
{
    returnDate();
}
intmain()
{
    Date d1;
    Func3();
    return0;
}
ii.Date对象做临时返回值传值
Date Func3()
{
    returnDate();
}
intmain()
{
//情况一
    Date d1;
    d1 = Func3();
    
    return0;
}
输出结果为:
构造函数拷贝赋值函数的N种调用情况

没有调用拷贝构造函数的原因是编译器对其做了优化处理—Func3函数返回一个临时变量,
本来函数的返回值会通过拷贝构造创建一个临时变量,再将临时变量的值赋给d3,但由于
此时已经是一个临时变量,所以编译器就自动进行了优化。
//情况二

构造函数拷贝赋值函数的N种调用情况



//情况三
构造函数拷贝赋值函数的N种调用情况

通过上述三种情况的对比,显然情况三更优化!

2.Test1中调用了_2_次AA的拷贝构造函数,_1__次AA的赋值运算符函数的重载。
Test2中调用了_2__次AA的拷贝构造函数,_0__次AA的赋值运算符函数的重载。
Test3中调用了_3__次AA的拷贝构造函数,0_次AA的赋值运算符函数的重载。
classAA
{};
AA f (AA a)
{
returna ;
}
voidTest1 ()
{
AA a1 ;              
a1 = f(a1);
}
voidTest2 ()
{
AA a1 ;
AA a2 = f(a1);
}
voidTest3 ()
{
AA a1 ;
AA a2 = f(f(a1));
}
分析如下:

  构造函数拷贝赋值函数的N种调用情况构造函数拷贝赋值函数的N种调用情况
构造函数拷贝赋值函数的N种调用情况