C++中Fraction结构体operator+报错:无法绑定非const左值引用到右值
Fraction加法运算符报错问题解析
1. 先搞明白lvalue和rvalue
- lvalue(左值):有持久内存地址的对象,能放在赋值号左边,比如你定义的
a、c,可以用&取地址。 - rvalue(右值):临时生成的对象,没有持久地址,只能放赋值号右边,比如
a+b的运算结果,不能用&取地址,用完就销毁。
2. 报错的根本原因
你写的operator+应该是返回了非const的左值引用(Fraction&),但a+b生成的是临时右值。C++不允许把非const引用绑定到右值——因为引用需要指向一个能长期存在的对象,临时对象用完就没了,绑定引用会导致无效的悬垂引用。
而把a+b赋值给c再输出没问题,是因为赋值操作把临时对象的值拷贝到了c这个有持久地址的变量里,之后操作的是合法的左值c。
3. 代码修正方案
加法运算会生成新的Fraction对象,正确的做法是返回对象本身,而不是引用:
错误写法(触发报错)
// 错误:返回局部对象的引用,且是非const引用 Fraction& operator+(const Fraction& lhs, const Fraction& rhs) { Fraction res; // 计算分子分母的逻辑 return res; // 局部对象res函数结束就销毁,返回引用直接炸 }
正确写法(推荐)
// 返回值,生成的临时对象可以被正常使用 Fraction operator+(const Fraction& lhs, const Fraction& rhs) { Fraction res; // 计算逻辑:通分后相加 res.numerator = lhs.numerator * rhs.denominator + rhs.numerator * lhs.denominator; res.denominator = lhs.denominator * rhs.denominator; // 这里可以加约分的逻辑,比如找最大公约数化简 return res; }
特殊场景的可选写法(不推荐普通加法用)
如果你的加法逻辑是返回一个已经存在的持久对象(比如全局静态对象),可以返回const引用,但这种写法有线程安全问题,一般加法不用:
const Fraction& operator+(const Fraction& lhs, const Fraction& rhs) { static Fraction res; // 静态对象,生命周期和程序一致 res.numerator = lhs.numerator * rhs.denominator + rhs.numerator * lhs.denominator; res.denominator = lhs.denominator * rhs.denominator; return res; }
4. 补充提醒
- 你的
operator<<应该是接收const Fraction&参数,所以它既能绑定左值(比如c),也能绑定临时右值——如果修正operator+返回值,直接cout << a+b就会正常运行。 - 永远不要返回局部对象的引用,不管是什么运算符,这会导致悬垂引用,程序运行时大概率出问题。
内容的提问来源于stack exchange,提问作者Nil
相关产品推荐
相关产品推荐

