C++-----对象的生命周期(二)

知识的积累在于日积月累,每天掌握一点点,你会变得更加强大。

关于如何分析对象的生命周期,可以参照博文(https://mp.csdn.net/postedit/89514602)。本片文章主要针对如何对程序进行优化,减少一些无关函数的调用,以提高程序的执行效率。

我们首先给出一段程序:

#include<iostream>
using namespace std;
class Test
{
public:
	Test(int data = 100):ma(data)      //构造函数
	{cout<<"Test(int)"<<endl;}

	~Test()                            //析构函数
	{cout<<"~Test()"<<endl;}

	Test(const Test &src):ma(src.ma)   //拷贝构造函数
	{cout<<"Test(const Test&)"<<endl;}

	Test&operator=(const Test &src)    //赋值运算符重载函数
	{
		cout<<"operator="<<endl;
		ma = src.ma;
		return *this;
	}

	int getdata()
	{return ma;}
private:
	int ma;
};

Test GetTestObject(Test t)
{
	int value = t.getdata();
	Test tmp(value);
	return tmp;
}
int main()
{
	Test t1;
	Test t2;
	t2 = GetTestObject(t1);
	cout<<t2.getdata()<<endl;
	return 0;
}

 执行结果:

Test(int)                 //普通构造t1
Test(int)                 //普通构造t2
Test(const Test&)         //传参的过程,相当于“t = t1”,调用拷贝构造
Test(int)                 //普通构造tmp
Test(const Test&)         //函数返回时,相当于“t2 = tmp”,调用拷贝构造
~Test()                   //析构tmp
~Test()                   //析构t
operator=                 //临时对象赋值t2
~Test()                   //析构临时对象
100          
~Test()                   //析构t2
~Test()                   //析构t1
//上述两处拷贝构造函数并非真正意义上的拷贝构造过程,具体将在后面进行说明

优化原则一:

函数调用需要传入对象时,应该按照按对象引用来传递。我们知道引用实际上就是别名,使用引用,其实就是在使用自己,这样会减少两个函数的调用开销。(拷贝构造函数和析构函数)

我们对上面代码做出修改,并输出执行结果:

#include<iostream>
using namespace std;
class Test
{
public:
	Test(int data = 100):ma(data)      //构造函数
	{cout<<"Test(int)"<<endl;}

	~Test()                            //析构函数
	{cout<<"~Test()"<<endl;}

	Test(const Test &src):ma(src.ma)   //拷贝构造函数
	{cout<<"Test(const Test&)"<<endl;}

	Test&operator=(const Test &src)    //赋值运算符重载函数
	{
		cout<<"operator="<<endl;
		ma = src.ma;
		return *this;
	}

	int getdata()
	{return ma;}
private:
	int ma;
};

Test GetTestObject(Test &t)
{
	int value = t.getdata();
	Test tmp(value);
	return tmp;
}
int main()
{
	Test t1;
	Test t2;
	t2 = GetTestObject(t1);
	cout<<t2.getdata()<<endl;
	return 0;
}

执行结果(这里不再进行详细阐述):

优化原则二:

函数返回值为对象的时候,应该返回一个临时对象,不要先定义对象,再返回,直接返回临时对象,临时对象的形式为:类型名(value);我们知道当返回值是临时对象时,编译系统会生成临时对象,由返回对象拷贝构造临时对象,当函数结束时,返回对象出作用域时自动调用析构函数。然后临时对象赋值给定义,临时对象自动调用析构函数释放自己。而当我们返回一个临时对象时,编译器会直接普通构造定义的对象。减少了函数的调用过程。

我们对上面代码做出修改,并输出执行结果:

#include<iostream>
using namespace std;
class Test
{
public:
	Test(int data = 100):ma(data)      //构造函数
	{
		cout<<"Test(int)"<< endl;
	}
	~Test()                            //析构函数
	{cout<<"~Test()"<<endl;}

	Test(const Test &src):ma(src.ma)   //拷贝构造函数
	{cout<<"Test(const Test&)"<<endl;}

	Test&operator=(const Test &src)    //赋值运算符重载函数
	{
		cout<<"operator="<<endl;
		ma = src.ma;
		return *this;
	}

	int getdata()
	{return ma;}
private:
	int ma;
	
};

Test GetTestObject(Test &t)
{
	int value = t.getdata();
	//Test tmp(value);
	return Test(value);
}
int main()
{
	Test t1(5);
	Test t2(8);
	t2 = GetTestObject(t1);
	cout<<t2.getdata()<<endl;
	return 0;
}

执行结果(这里不再进行详细阐述):

优化原则三:

调用返回对象的函数时,应该以初始化的方式调用,不要以赋值的方式调用。我们知道对于执行语句“t2 = GetTestObject(t1);临时对象会调用赋值函数对t2进行赋值并且临时对象会调用析构函数。而如果采用初始化的方式,则直接普通构造定义对象。
 

我们对上面代码做出修改,并输出执行结果:

#include<iostream>
using namespace std;

class Test
{
public:
	Test(int data = 100):ma(data)      //构造函数
	{
		cout<<"Test(int)" << endl;
	}
	~Test()                            //析构函数
	{cout<<"~Test()" << endl;}

	Test(const Test &src):ma(src.ma)   //拷贝构造函数
	{cout<<"Test(const Test&)"<< endl;}

	Test&operator=(const Test &src)    //赋值运算符重载函数
	{
		cout<<"operator=" <<endl;
		ma = src.ma;
		return *this;
	}

	int getdata()
	{return ma;}
private:
	int ma;
	
};

Test GetTestObject(Test &t)
{
	int value = t.getdata();
	//Test tmp(value);
	return Test(value);
}
int main()
{
	Test t1;
	Test t2 = GetTestObject(t1);
	cout<<t2.getdata()<<endl;
	return 0;
}

执行结果:

第二个Test(int)直接构造t2,并没有执行临时对象拷贝构造t2的过程

最后我们做出总结:

  • 函数调用传对象时,应该按对象引用来传递
  • 函数返回对象的时候,应该返回一个临时对象,不要先定义,再返回,应该直接返回临时对象 
  • 调用返回对象的函数时,应该以初始化的方式调用,不要以赋值的方式调用
  • 临时对象拷贝构造对象时,直接普通构造对象
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值