条款21:必须返回对象时,别妄想返回其reference

本文深入探讨了在编程实践中,为何不应返回对象的reference或pointer,特别是在栈空间和堆空间中。文章通过具体案例分析了返回reference可能导致的内存泄露和逻辑错误问题,并提供了安全的替代方案。

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

条款21:必须返回对象时,别妄想返回其reference
引用只是对象的一种别名当使用引用的时候,请确认他的另一个身份在哪?
class Rational
{
public:
	Rational(int x, int y) : m_x(x), m_y(y){}

	//返回const是属于类型保护,friend修饰,以后条款详说
	friend const Rational operator + (const Rational &lhs, const Rational &rhs)  
	{
		Rational temp(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y); //还有更好的做法
		return temp;
	}
private:
	int m_x;
	int m_y;
};
        实现+号重载,我们采用return value,根据前面条款,返回value会调用一系列拷贝构造函数,析构函数的成本,于是我们修改为return reference
	friend const Rational& operator + (const Rational &lhs, const Rational &rhs)  
	{
		Rational temp(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y); //还有更好的做法
		return temp;
	}
       +号返回的引用对象在哪?我们看到在函数中创建一个临时对象temp,这个是属于栈空间对象,跳出函数作用域被回收,则引用的对象已经不存在了,程序会出现不可意料的行为。
        上面我们提到函数实现还有一个更好的做法
	friend const Rational operator + (const Rational &lhs, const Rational &rhs)  
	{
		return Rational(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y); //标准做法
	}
       分析下:第一种做法是创建临时对象,调用构造函数初始化,返回时调用拷贝构造函数初始化存放返回值的外部变量,最后调用析构函数。而第二种是编译器直接创建临时对象并初始化外部变量,省去调用拷贝构造函数和析构函数。
       如果考虑到在heap里面创建对象不会容易被回收,并使用reference返回,那么这个代价更大。

	friend const Rational& operator + (const Rational &lhs, const Rational &rhs)  
	{
		return *(new Rational(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y));
	}
看下面调用
	Rational x(1,2), y(3, 4), z(5, 6);
	Rational r = x + y + z;
      调用了两次operator +,两次new调用分配内存,但没有合理的方法delete内存,因为没有合理的方法取得返回reference的那个指针,导致内存泄露。
     如果还是希望让函数返回reference而通过定义一个local-static对象替代heap对象,那么这个代价不比heap方法的小。

	friend const Rational& operator + (const Rational &lhs, const Rational &rhs)  
	{
		static Rational sRational(lhs.m_x + rhs.m_x, lhs.m_y + rhs.m_y);
		return sRational;
	}
使用了静态变量在多线程安全性中存在隐患这一个问题暂且不说,还有一个是调用判断相等时出现逻辑错误
调用==判断
	Rational x(1,2), y(3, 4), z(5, 6), w(7, 8);

	if ((x + y) == (z + w)) {
		cout<<"equal\n";
	}
       因为+号返回引用,而引用执行的对象时static,两次的+号返回reference其实是指向同一个对象,那==值判断永远相等。
记住
       绝不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个local static对象而有可能同时需要多个这样的对象.条款4已经为"在单线程环境中合理返回reference指向一个local static对象"提供一份设计实例.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值