c++ 产生临时对象的情况和解决方案

1 以传值的方式给函数攒底参数。

这个不用说,值传递。

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

举例1:

# include <iostream>

using namespace std;

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;
	};
	virtual ~CTempValue() //析构函数
	{
		cout << "调用了析构函数!" << endl;
	};

	CTempValue& operator=(const CTempValue& tmpv)
	{
		//不能用初始化列表,只有构造函数才有初始化列表
		val1 = tmpv.val1;
		val2 = tmpv.val2;
		cout << "调用了拷贝赋值运算符!" << endl;
		return *this;
	}


public:
	//int Add(CTempValue tobj); //普通成员函数
	int Add(CTempValue& tobj); //普通成员函数
};


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

//int CTempValue::Add(CTempValue tobj)
//{
//	int tmp = tobj.val1 + tobj.val2;
//	tobj.val1 = 1000;            //这里修改对外界没什么影响
//	return tmp;
//}
int CTempValue::Add(CTempValue& tobj)
{
	int tmp = tobj.val1 + tobj.val2;
	tobj.val1 = 1000;            //这里修改对外界直接产生影响
	return tmp;
}

int main(int argc, char** argv)
{
    CTempValue sum;
    sum = 1000;
    return 0;
}
===================================
(base) ➜  ./b
调用了构造函数!
val1 = 0
val2 = 0
调用了构造函数!
val1 = 1000
val2 = 0
调用了拷贝赋值运算符!
调用了析构函数!
调用了析构函数!

将100赋值给sum,会触发 1000为构造函数的第一个形参赋值,构造一个临时对象,再调用复制赋值运算符,将值赋值给sum。

举例2:

#include <string>

using namespace std;

int calc(const string& strsource, char ch)
{
	const char* p = strsource.c_str();
	int icount = 0;
	//....具体的统计代码
	return icount;
}
int main(int argc, char** argv){


	char mystr[100] = "I love China,oh,yeah!";
	int result = calc(mystr, 'o'); //看调用的是哪个calc函数

    return 0;
}

由于calc的形参和mystr的类型不一样,在调用函数的时候,函数calc第一个参数会触发编译器为我们产生一个类型为string的临时对象,临时对象的构造方式就是用mystr作为参数,调用string的构造函数,这样形参就绑定到了这个string临时对象上。当calc返回的时候,这个临时对象会被自动销毁。

注意:string& strsource前必须加const,strsource是一个引用,如果不加const系统会认为,该值有可能会被修改,但是,strsource是一个临时对象,不能被修改,所以c++标准不允许这种倾向。c++只会为const引用产生临时对象,并不会为非const引用创建临时对象。

3 函数返回对象的时候

函数返回对象,内部会通过要返回的值调用拷贝构造函数创建临时对象,再析构原对象。

CTempValue Double(CTempValue& ts)
{
    CTempValue a(ts.val1 * 2, ts.val2 * 2);
	return a;
}
int main(int argc, char** argv)
{
    
	CTempValue ts1(10, 20);
    CTempValue ts3 = Double(ts1);
    cout << "p = "<< &ts3 <<endl;
    return 0;
}

==================
调用了构造函数! p = 0x16dca9460          ==ts1
val1 = 10
val2 = 20
调用了构造函数! p = 0x16dca93e0         == a
val1 = 20
val2 = 40
调用了拷贝构造函数! p = 0x16dca9440     ==临时对象
调用了析构函数! p = 0x16dca93e0        == 析构a
调用了拷贝构造函数! p = 0x16dca9450     == 临时对象到ts3拷贝构造
调用了析构函数! p = 0x16dca9440        == 析构临时对象
p = 0x16dca9450
调用了析构函数! p = 0x16dca9450        == 析构ts3
调用了析构函数! p = 0x16dca9460        == 洗头ts1

如果开启编译优化,ts3会直接接管临时对象。少一个拷贝构造。【double函数返回的临时对象直接使用了ts3的预留空间】。

4 类外的运算符之中的优化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值