3

据此:运算符重载

class X {
  X& operator++()
  {
    // do actual increment
    return *this;
  }
  X operator++(int)
  {
    X tmp(*this);
    operator++();
    return tmp;
  }
};

是实现++运算符的方式。第二个(后缀运算符)按值而不是按引用返回。这很清楚,因为我们不能返回对本地对象的引用。因此tmp,我们不是在堆栈上创建对象,而是在堆上创建它并返回对它的引用。所以我们可以避免额外的副本。所以我的问题是,以下是否有任何问题:

class X {
  X& operator++()
  {
    // do actual increment
    return *this;
  }
  X& operator++(int)
  {
    X* tmp = new X(*this);
    operator++();
    return *tmp;
  }
};
4

3 回答 3

4

调用者现在必须处理删除内存。

于 2013-06-15T08:50:34.720 回答
1

如果您的目标是避免额外的副本,请记住可能不会有额外的副本。RVO会避免它——返回值将直接放入调用者的变量 X 中,优化掉副本。

于 2013-06-15T09:23:55.777 回答
1

因此,我们不是在堆栈上创建 tmp 对象,而是在堆上创建它并返回对它的引用。所以我们可以避免额外的副本。

根据 RVO,在大多数情况下没有额外的副本。x里面的值operator++直接上移作为返回值。检查这个:

#include <iostream>

class X 
{
    public:

        X() {}
        X( const X & x ) {
            std::cout << "copy" << std::endl;
        }

        X& operator++()
        {
            // do actual increment
            return *this;
        }
        X& operator++(int)
        {
            X x;
            operator++();
            return x;
        }
};

int main()
{
    X x;
    x++;

    return 0;
}

无副本(仅由 vc7 测试)。但是,您的实现确实复制了这一行:

X tmp(*this);

或者在这个:

X* tmp = new X(*this);
于 2013-06-15T09:24:46.093 回答