实现前缀运算符++



来源http://www.learncpp.com/cpp-tutorial/97-overloading-the-increment-and-decrement-operators/

类别声明

class Digit
{
private:
    int m_nDigit;
public:
    Digit(int nDigit=0)
    {
        m_nDigit = nDigit;
    }
    Digit& operator++();
    Digit& operator--();
    int GetDigit() const { return m_nDigit; }
};

operator++ 的实现

Digit& Digit::operator++()
{
    // If our number is already at 9, wrap around to 0
    if (m_nDigit == 9)
        m_nDigit = 0;
    // otherwise just increment to next number
    else
        ++m_nDigit;
    return *this;
}

我对operator++ 的替代实现

Digit& Digit::operator++()
{
    return Digit(m_nDigit == 9 ? 0 : (m_nDigit + 1));
}

我想了解

  1. 如果像我所做的那样创建一个新对象有任何缺点,以及
  2. 关于如何选择其中一个实现

像您所做的那样创建对象肯定有缺点:

  1. 它不会编译。不可能将非常量引用绑定到临时引用。

  2. 即使它进行了编译,也不会执行正确的操作(您的版本使operator++m_nDigit设置为9,另一个版本递增m_nDigit,在达到10时循环)。

  3. 即使它确实编译并做了正确的事情,也会非常不安全。返回的引用将绑定到一个临时对象,该对象将在函数返回之前被销毁,这意味着任何访问operator++返回值引用的对象的尝试都将导致未定义的行为。

要在这两种实现之间进行选择,您应该选择一种可编译、正确且安全的实现。

三元运算符有问题。此外,您返回的是对象的副本,而不是对象本身,如果您试图重载运算符以像内置类型一样工作,则应始终返回对对象的引用。

我认为你应该这样做:

Digit& Digit::operator++()
{
    m_nDigit = (m_nDigit == 9 ? 0 : m_nDigit++);
    return *this;
}

或者像这样:

Digit& Digit::operator++()
{
    m_nDigit = (++m_nDigit % 10);
    return *this;
}

创建一个新对象的缺点是在类似的代码中

Digit d;
++d;

我希望d的值会改变,而对于一个新对象,它不会改变。这个运算符在很多情况下都是这样使用的(不将它分配给变量),所以如果你不增加并返回同一个对象,你就不能这样使用它。

在您的替代实现中,您有两个问题:

  1. 而不是CCD_ 9做CCD_。当前m_nDigit将始终为9,返回值将始终为0。

  2. 您应该更改m_nDigit的值。返回0时,您不会。

return语句有问题,因为运算符应该更改操作数的值,而不是创建新对象。

编辑

要澄清问题,请考虑代码:

Digit x;
x++;

您希望x作为此代码的结果是什么?我希望是1。使用运算符时,它保持不变。

  1. m_nDigit = 9是一个赋值,并且将始终被评估为true
  2. 返回对象的副本,但返回类型是引用。这可能会影响您(请参阅是否可以通过引用返回临时对象)
  3. 为什么不m_nDigit = (m_nDigit + 1) % 9;

最新更新