临时对象和局部对象以及函数返回值优化

本文详细解析了C++中临时对象的概念及其应用场景,包括隐式类型转换和函数返回对象两种情况,并介绍了如何优化函数返回对象的过程以减少不必要的构造和析构操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们先看一个代码:

void swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}

大部分人称temp为临时对象,实际上,应该称为局部对象更合理,真正的临时对象是不可见的——不会出现在你的源代码中。只要你产生一个non-heap 对象而没有为它命名,便诞生了一个临时对象。

匿名对象(临时对象)通常发生于两种情况:

1.隐式类型转换;

2.函数返回对象;


首先看一下隐式类型转换:

size_t countChar(const string& str, char ch)//计算string中字符ch出现的次数
{

}

char buffer[] = "Hello World!";
countChar(buffer, l);

我们看一下countChar的调用动作,第一个实参是char数组,但形参是const string&,必须消除类型不吻合,函数才能正常调用,因此,编译器应该要产生一个临时的string对象,并以buffer为参数构造一个string,于是countChar的str绑定到该临时string,当函数返回时,销毁该临时string。

 

这里,函数参数是const string&,但如果是string& ,会产生临时对象么?答案是:不会。考虑下面这个函数:

char buffer[] = "Hello World!";
void uppercasify(string& str)
{

}

uppercasify(buffer);
这时,是不会产生临时对象的。因为函数的参数是string& str,如果通过char数组产生一个临时string和函数参数str绑定,因为是引用,该函数对str的改动,应该反映到char数组buffer上,但是,事实是该动反映到临时对象上,这和我们的预想肯定相违背。因此,编译器是进制这种匿名对象产生的。

因此,我们可以总结:

当对象被传递给一个reference-to-const参数时,才会产生匿名对象。

如果对象传递给一个reference-to-non-const,是不会产生 匿名对象的,必须给它一个相符的类型。


上面说到的另一种情况是函数返回对象。

class Rational
{
public:
	Rational(int numerator = 0, int denominator = 1);
	int  numerator()const;
	int denominator()const;
};

const Rational operator*(const Rational& lhs, const Rational& rhs)
{ 
	Rational result(lhs.numerator()*rhs.numerator(), lhs.denominator()*rhs.denominator());
	return result;
}


当我们

Rational a = 10;
Rational b(1, 2);
Rational c = a * b;

很明显,operator*()内产生了一个局部对像,那么就需要构造函数和析构函数的调用,如何消除这个额外负担?

我们把operator*()函数稍微修改一下:

const Rational operator*(const Rational& lhs, const Rational& rhs)
{ 
	return Rational(lhs.numerator()*rhs.numerator(), lhs.denominator()*rhs.denominator());
}
这里看着好像并没有任何优化,因为还是需要产生临时对象,那么就还是需要构造和析构函数的调用。实际上,C++允许编译器将临时对象优化,使它们不存在。
于是:

Rational a = 10;
Rational b(1, 2);
Rational c = a * b;
它可以将return 表达式所定义的对象构造于c的内存内,那么,这个operator*就不需要临时对象,也就不用在构造函数 和析构函数方面的花销。

因此,当函数必须返回一个value时,尽量不要出现局部变量,而是临时变量,而编译器可以通过优化帮我们消除临时变量。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值