C++基础——匿名对象介绍、拷贝对象时的一些编译器优化

        

目录

 创建对象的几种方式:

匿名对象的创建格式: 

二.编译器对于拷贝对象做出的优化

场景一: 

检测:

优化:

检测: 

场景二:

检测:

优化: 

场景三:

检测: 

优化: 

场景四:

优化: 

检测:

整体优化总结:


        通过C++长时间的学习,我们已经学会了好多通过类定义对象的方法,例如:

class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)构造" << endl;
	}
	A(const A& a1) {
		cout << "A(const A& a1)拷贝构造" << endl;
	}
	~A()
	{
		cout << "~A()析构" << endl;
	}

	void Print() {
		cout << _a << endl;
	}
private:
	int _a;
};


class Solution {
public:
	Solution(double s= 3.14)
		:_st(s)
	{
		cout << "Solution(double s)构造" << endl;
	}

	int Sum_Solution(int n) {
		//...
		return n;
	}
	~Solution()
	{
		cout << "~Solution()析构" << endl;
	}
private:
	double _st;
};

 创建对象的几种方式:

int main() {
	//创建对象的方式
	A a1,a2;	//方式1:
	A a3(10);	//方式2:
	A a4(a1);	//方式3:
	A a5 = 20;	//方式4:

        方式1:编译器会调用构造函数去创建对象;

        方式2:在调用构造函数的同时给予实参直接赋值;

        方式3:编译器会调用拷贝构造去创建对象;

        方式4:这与方式3等价,且这会让编译器采用隐式类型转换。 

A a6();	

       要特别注意上面这种创建对象方式,该种方式有歧义,会让编译器不知道该调用构造,还是拷贝构造,所以即使运行成功了,编译器也不会生成a6对象! 

今天我再来介绍一种定义对象的方法,这种方法被称为匿名对象。

匿名对象的创建格式: 

类名();

例: 

调用结果: 

        解析:通过调试出的结果来看,类A,类Solution的匿名对象刚调用完构造函数就调用析构函数了 ,而之前我们创建的对象都是最后会调用析构函数,因此我们得出一个结论:匿名对象的生命周期是在当前行,执行A();调用构造函数,这行完了之后,跳转到下一行时,编译器会调用析构函数。而一般对象的生命周期是一个局部周期,局部结束才会被销毁。这就是一般对象和匿名对象最大的差别!

        那么匿名对象到底有什么用呢?

        其实你可以理解它是为懒人专用而研发的,~~哈哈哈

例:

一般对象调用函数时:

A a1;
a1.Print();


Solution s1;
int n=s1.Sum_Solution(25);

而匿名对象调用函数时:

    A().Print();
    int n=Solution().Sum_Solution(70);

一般对象调用函数需要先创建对象,其次才能再调用函数,需要两行;而匿名对象调用函数时一行就可以解决的,

二.编译器对于拷贝对象做出的优化

#include<iostream>
using namespace std;


class A{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)构造" << endl;
	}
	A(const A& aa)
		:_a(aa._a)
	{
		cout << "A(const A& aa)拷贝构造" << endl;
	}
	A& operator=(const A& aa){
		cout << "A& operator=(const A& aa)重载函数" << endl;
		if (this != &aa)
		{
			_a = aa._a;
		}
		return *this;
	}
	~A(){
		cout << "~A()析构" << endl;
	}
private:
	int _a;
};

void f1(A aa){}

A f2(){
	A aa(10);
	return aa;
}

A f3()
{	//注:F2与F3几乎等价
	return A(10);	//返回匿名对象
}


场景一: 

int main() {
	A a1;        //构造
	a1 = 20;	 //构造+拷贝构造+赋值运算符重载
    }

检测:

         第一句调用构造函数创建对象,第二句则是将通过常量20创建临时类A对象(调用构造函数),然后a1拷贝复制(调用拷贝构造)临时类A对象值,总计调用:构造+拷贝构造+赋值重载函数。

优化:

//优化场景1:以下这句与上面等价
	A a1 = 20;	

检测: 

         优化后只调用了构造函数。


场景二:

    A a2(2022);
	f1(a2);	
	//以上两句共调用:构造+拷贝构造

检测:

        解析:A a2(2022)是正常的调用构造函数+实参赋值创建对象,因为f1函数形参是类类型参数,这是调用构造函数的情况之一,所以总计调用:构造+拷贝构造 

优化: 

//优化2:注,以下这句与上面等价
	f1(A(2022));		

        优化后只调用构造函数。         


场景三:

f2();		//构造+拷贝构造

         解析:f2函数内部因为创建对象,所以调用构造函数,且返回值为类类型对象,这也是拷贝构造函数调用的情况之一,所以f2函数总计调用:构造+拷贝构造

    A ret;
    ret=f2();	//总结:构造+拷贝构造+拷贝构造

检测: 

        总计调用:构造+构造+拷贝构造+赋值重载函数 

优化: 

//优化3:下面这句与上面两句等价
	A ret = f2();	

        优化后总计调用:构造+拷贝构造 


场景四:

    A ret = f2();	//构造+拷贝构造

         总计调用:构造+拷贝构造 

优化: 

//优化4:极致优化
	A ret2 = f3();

检测:

         优化后总计调用一次构造函数。

整体优化总结:

        能一句能搞定的事情不要分开去编写,不要做中间商!中间商不仅赚不了差价,而且还会赔本!!!

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙予清的zzz~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值