临时对象深入探讨、解析,提高性能手段[转]

临时对象深入探讨、解析,提高性能手段[转]

临时对象的概念

  • 示例:i++, ++i
int i = 1;
int &&r1 = i++; //r1和i之间没有什么关系。
//这个临时变量的生命周期与r1绑定了
r1 = 19;
i = 80;
  • 另外一些临时对象,是因为我们代码书写问题而产生的,统一称临时变量为临时对象。
  • new /delete处理堆上的问题,这里的临时对象基本属于栈的问题。

产生临时对象的情况和解决

1. 以传值的方式给函数传递参数

class CTempValue{
public:
	int val1;
	int val2;
public:
	CTempValue(int v1 = 0, int v2 = 0);

	CTempValue(const CTempValue& t) :val1(t.val1), val2(t.val2) //拷贝构造函数
	{
		cout << "调用了拷贝构造函数" << endl;
	}
	//拷贝赋值运算符
	CTempValue & operator=(const CTempValue& tmpv){
		val1 = tmpv.val1;
		val2 = tmpv.val2;
		cout << "调用了拷贝赋值运算符" << endl;
		return *this;
	}

	virtual ~CTempValue() //析构函数
	{
		cout << "调用了析构函数" << endl;
	}

public:
	int Add(CTempValue ts); //普通函数


};

CTempValue::CTempValue(int v1, int v2) :val1(v1), val2(v2){
	cout << "调用了构造函数" << endl;
	cout << "val1 = " << val1 << endl;
	cout << "val2 = " << val2 << endl;
}

int CTempValue::Add(CTempValue ts){
	int tmp = ts.val1 + ts.val2;
	ts.val1 = 1000; //这里修改值对外界没有影响
	return tmp;
}
CTempValue tm(10, 20); //调用析构函数
int sum = tm.Add(tm); //这个会导致拷贝构造函数的执行
cout << "Sum =" << sum << endl;
cout << "tm.val1 =" << tm.val1 << endl;
  • 输出:

  •  建议:将传值改成引用。
int Add(CTempValue& ts); //普通函数

2 类型转换生成的临时对象/隐式类型转换以保证函数调用成功

CTempValue sum1;
sum1 = 1000; // 这里产生了一个真正的临时对象
  • 输出:

  •  分析:
    • (1) 用1000这个数字创建了一个类型为CTempValue 的临时对象
    • (2) 调用拷贝赋值运算符把这个临时对象里边的各个成员值赋值给了sum对象
    • (3) 销毁这个临时创建的CTempValue对象。
  •  优化写法:
CTempValue sum1 = 1000; //把定义对象和给对象初值放在一行上。
  • 输出:

  •  分析:
    • 为sum1对象预留了空间,用1000构造sum1对象,而且是直接构造在sum1对象预留空间里。

隐式类型转换以保证函数调用成功

//统计字符ch在字符串strsource里出现的次数,把次数返回去
int calc(const string strsource, char ch){
//int calc(const string& strsource, char ch){
	const char *p = strsource.c_str();
	int icount = 0;
	//.....具体的统计代码

	return icount;
}
char mystr[100] = "I Love China, oh yeah!";
int result = calc(mystr, 'o'); //char[] 会转成临时string对象
  • 如果上面函数参数改成:   int calc(string strsource, char ch) , 也就是去掉const 就会编译报错。
  • C++语言只会为const引用(const string & strsource)产生临时变量,而不会为非const引用(const引用 string & strsource)这种参数产生临时变量。

函数返回对象的时候

CTempValue Double(CTempValue &ts){
	CTempValue tmpm; //这个会消耗我们一个构造函数和一个析构函数的调用
	tmpm.val1 = ts.val1 * 2;
	tmpm.val2 = ts.val2 * 2;
	return tmpm;
}
  • 分析 :
    • Double()函数引起的消耗
    • CTempValue tmpm; //会消耗一个构造函数和一个析构函数
    • return tmpm; //产生临时对象,占用衣蛾拷贝构造函数和析构函数。
CTempValue ts1(10, 20);
Double(ts1); //因为返回临时对象导致占用了一个拷贝构造函数和一个析构函数。
//CTempValue ts3 = Double(ts1);
//CTempValue &&ts4 = Double(ts1); // 临时对象是一种右值
  • 调用一次 Double(ts1) 输出:

  •  优化:
CTempValue Double(CTempValue &ts){
	return CTempValue(ts.val1 * 2, ts.val2 * 2);
}
  • 再举一例:介绍知识点:类外运算符重载。
    • 类内:Time &Time::operator(const Time & tmpTime) {.... return *this };
  • 类外示例:
class mynum{
public:
	int num1;
	int num2;
};

mynum operator+(mynum& t1, mynum & t2){
	mynum result;
	result.num1 = t1.num1 + t2.num1;
	result.num2 = t1.num2 + t2.num2;
	return result;
}
  • 可优化为:
mynum operator+(mynum& t1, mynum & t2){
	return mynum(t1.num1 + t2.num1, t1.num2 + t2.num2);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值