我一直在尝试编写Fraction类并重载其某些运算符(+,-,-,/ ...)。一开始,我尝试这样做:

Fraction& operator+(Fraction& rightOp)
{
    Fraction result;
    result.num = num * rightOp.den + den * rightOp.num;
    result.den = den * rightOp.den;;
    return result;
}


这产生了尴尬的结果。在测试时,如果我使用过:

Fraction a(2,3);
Fraction b(4,5);
Fraction c = a + b;
cout << c << endl;


它将正确打印。但是,如果我使用过:

Fraction a(2,3);
Fraction b(4,5);
Fraction c;
c = a + b;
cout << c << endl;


它会打印-858993460 / -858993460。

然后,当我尝试将重载函数更改为:

Fraction& operator+(Fraction& rightOp)
{
    Fraction* result = new Fraction;
    result->num = num * rightOp.den + den * rightOp.num;
    result->den = den * rightOp.den;
    return *result;
}


一切都会很好。这让我对指向C ++中的类感到困惑,我不太明白为什么第一个在特定情况下会失败。我将不胜感激。

提前致谢。

注意:
运算符<
friend ostream& operator<<(ostream& out, Fraction& f)
{
    out << f.num << "/" << f.den << endl;
    return out;
}

最佳答案

Fraction& operator+(Fraction& rightOp)
{
    Fraction result;
    result.num = num * rightOp.den + den * rightOp.num;
    result.den = den * rightOp.den;;
    return result;
}


问题在于它正在返回对局部变量的引用。函数结束时将销毁局部变量,因此该引用引用了无效的对象。

使用new可以为您解决问题,因为它可以动态分配result对象。在功能结束时不会破坏此类对象。但是,这里肯定不是解决方案。 operator+的用户完全不清楚返回的引用是指动态分配的对象,将来需要delete d。永远不要给您的用户带来负担。

相反,您应该更改函数,使其按值返回:

Fraction operator+(Fraction& rightOp)
{
  // ...
  return result;
}


现在将返回result的副本,因此result是否在函数末尾销毁并不重要。

作为附加说明,您可能希望函数采用const Fraction&参数。当第二个操作数是一个右值(通常是一个临时对象)时,这将允许调用它。

10-08 07:52