小结 | C++对传参和传返回值的优化

来源:互联网 发布:趣玩网络 编辑:程序博客网 时间:2024/05/18 03:29

编译器对传参和返回值的优化

在Date类中的每一个成员函数中,打印相应的函数类型。以表示调用了该函数。

class Date{public:    Date()    {        cout << "Date()" << endl;    }    Date(const Date&s)    {        cout << "Date(const Date&s)" << endl;    }    Date& operator=(const Date&s)    {        cout << "Date& operator=(const Date&s)" << endl;        return *this;    }    ~Date()    {        cout << "~Date()" << endl;    }};

情况一

//函数void F1(Date d){}//调用Date a;F1(a);

这里写图片描述
分析:
1)构造是创建对象 a
2)拷贝构造是临时变量 d 的创建
3)第一个析构是临时变量 d作用域结束的析构
4)第二个析构是对对象a的 析构

情况二

//函数Date F2(){    Date tmp;    return tmp;}//调用F2();

这里写图片描述
分析:
1)局部变量tmp的创建
2)用于返回的临时变量的拷贝构造
3)局部变量tmp的析构
4)临时变量的析构

情况三

//函数Date F3(){    static Date tmp;    return tmp;}//调用F3();

这里写图片描述
分析:
1)跟情况二一样
优化:
static并不会有所优化,因为static的作用域是在当前函数里面

情况四

//函数Date& F4(){    static Date tmp;    return tmp;}//调用F4();

这里写图片描述
分析:
1)静态局部变量tmp的创建
2)静态局部变量tmp的析构
优化:
一次优化
对比于情况三,因为return是引用返回,编译器明确知道这个tmp就是用来返回的,编译器优化了拷贝构造临时变量。

情况五

//函数void F5(Date d){}//调用F5(Date());

这里写图片描述
分析:
1)匿名对象Date()的创建
2)匿名对象Date()的析构
优化:
一次优化
对比于情况一,匿名对象直接用于传参,编译器可以将拷贝构造优化

情况六

//函数Date F6(){    return Date();}//调用F6();

这里写图片描述
分析:
1)匿名对象Date()的创建
2)匿名对象Date()的析构
优化:
一次优化
对比于情况二,匿名对象用于返回的时候,编译器优化了作为返回值的临时变量的拷贝构造。

情况七

//函数Date F7(){    Date tmp;    return tmp;}//调用Date a;a = F7();

这里写图片描述
分析:
1)对象a的创建
2)局部变量tmp的创建
3)返回值临时变量的拷贝构造
4)局部变量tmp的析构
5)F7()的返回值对a的赋值运算符的重载
6)返回值临时变量的析构
7)对象a的析构
优化:
这个是没有一丝编译器优化的程序

情况八

//函数Date F8(){    Date tmp;    return tmp;}//调用Date a = F8();

这里写图片描述
分析:
1)对象a 的创建
2)返回值临时变量的拷贝构造
3)返回值临时变量的析构
4)对象a的析构
优化:
有两个优化。
对比于情况七,(1)因为F8()的返回值,直接在a构造的时候对a进行赋值运算符的重载,编译器直接优化了赋值运算符的重载(2)在F8()内,局部变量tmp的创建与析构被编译器优化

情况九

//函数Date F9(){    return Date();}//调用Date a = F9();

这里写图片描述
分析:
1)对象a的创建
2)对象a的析构
优化:
两次优化
对于情况七,(1)因为F9()的返回值,直接在a构造的时候对a进行赋值运算符的重载,编译器直接优化了赋值运算符的重载(2)在F9()内,返回值临时变量的拷贝构造用匿名对象作为返回值,编译器优化了

测试

Date Func(Date d){    return d;}

1)Test1
调用了 次Date的拷贝构造函数,
调用了 次Date的赋值运算符函数的重载。

void Test1(){    Date d1;    d1 = Func(d1);}

这里写图片描述

2)Test2
调用了 次Date的拷贝构造函数
调用了 次Date的赋值运算符函数的重载。

void Test2(){    Date d1;    Date d2 = Func(d1);}

这里写图片描述

3)Test3
调用了 次Date的拷贝构造函数,
调用了 次Date的赋值运算符函数的重载。

void Test3(){    Date d1;    Date a2 = Func(Func(d1));}

这里写图片描述

这里写图片描述

原创粉丝点击