实现前缀运算符++

时间:2012-02-26 05:07:54

标签: c++

来自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. 关于如何选择其中一种实施方式?

4 个答案:

答案 0 :(得分:4)

创建对象肯定有缺点:

  1. 不会编译。将非const引用绑定到临时引用是不可能的。

  2. 即使它编译了它也不会执行正确的操作(您的版本会将operator++设置为m_nDigit9,其他版本会增加m_nDigit,到达10时环绕。)

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

  4. 要在两个实现之间进行选择,您应该选择一个编译,正确且安全的实现。

答案 1 :(得分:4)

您遇到三元运算符问题。您还要返回对象的副本而不是对象本身,如果您尝试重载操作符以像内置类型一样工作,则应始终返回对该对象的引用。

我认为你应该这样做:

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的值能够改变,而新的对象却没有。在许多情况下,此操作符就像这样使用(不将其分配给变量),因此如果不增加并返回相同的对象,则不能像这样使用它。

答案 2 :(得分:3)

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

  1. 而非m_nDigit = 9执行m_nDigit == 9。目前m_nDigit始终为9,返回值始终为0.

  2. 您应该更改m_nDigit的值。返回0时 - 你没有。

  3. 返回语句有问题,因为操作符应该更改操作数的值,而不是创建新对象。

    修改

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

    Digit x;
    x++;
    

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

答案 3 :(得分:2)

  1. m_nDigit = 9是一项作业,将始终评估为true
  2. 您返回对象的副本,但返回类型是引用。这可能会让你感到困惑(见Is returning a temp-object by reference possible)。
  3. 为什么不m_nDigit = (m_nDigit + 1) % 9;