3

我将其作为个人练习,并希望确保我做对并正确理解它。我有一个带有成员行和列的坐标类。我想重载 + 和 += 运算符。这是我的代码:

Coordinate& Coordinate :: operator+= (const Coordinate& rhs){
    this->m_Row += rhs.m_Row;
    this->m_Column += rhs.m_Column;

    return *this;
}

Coordinate& operator+ (const Coordinate& lhs, const Coordinate& rhs) {
    return Coordinate(lhs) += rhs;
}

在哪里

friend Coordinate& operator + (const Coordinate& lhs, const Coordinate& rhs);

是 Coordinate 类中定义的友元函数。

这段代码有什么陷阱吗?

以下是我对这些工作原理的理解:

operator += 

rhsm_Row 和 m_Column 添加到this成员。返回 a reference to the object pointed by this pointer,从而避免由于复制构造函数而创建另一个对象。

operator +

使用复制构造函数(让我们调用它)创建一个本地对象lhs(因为lhs它是一个常量,我们不想修改它的内容localObj)。调用执行加法的+=成员运算符。localObj返回 areference to this localObj以便我们不会由于复制构造函数而创建另一个对象,否则。

现在,最后一个语句与我有关,因为我正在返回对本地对象的引用。一旦函数(运算符+)超出范围,localObj将被销毁,返回的引用将指向已被销毁的对象。我对此的理解正确吗?

如果是这样,我应该如何解决它?

编辑: 在所有答案和我学到的东西之后:这是我的坐标类现在的样子:http ://rextester.com/MJJI7394

4

2 回答 2

6

你担心是对的,你在这里返回一个临时的引用:

Coordinate& operator+ (const Coordinate& lhs, const Coordinate& rhs) {
    return Coordinate(lhs) += rhs;
}

您需要按值返回 a Coordinate,例如:

Coordinate operator+ (Coordinate lhs, const Coordinate& rhs) {
    return lhs += rhs;
}

在上面的示例中,我们复制了第一个参数,而不是获取引用然后复制到函数体中。然后我们+=按值返回 on 的结果。

使用此设置,无需声明operator+为朋友。

有关更多信息,请参阅此 SO 链接,并感谢 @Blastfurnace 指出它。

于 2012-08-11T17:51:14.160 回答
0

就个人而言,我会operator+=()operator+()and来定义operator=()

Coordinate operator+(const Coordinate& lhs, const Coordinate& rhs) {
  return Coordinate(lhs.getRow() + rhs.getRow(), lhs.getCol() + rhs.getCol();
}

const Coordinate& operator=(Coordinate& lhs, const Coordinate& rhs) {
  lhs.setRow(rhs.getRow());
  lhs.setCol(rhs.setCol());

  return lhs;
}

const Coordinate& operator+=(Coordinate& lhs, const Coordinate&rhs) {
  return lhs = lhs + rhs;
}

我在这里使用 setter 和 getter。或者,您可以使用朋友和/或成员函数。请注意,所有返回引用的函数都返回传入的参数,因此对本地或临时对象的引用没有问题。

于 2012-08-11T18:11:56.193 回答