前缀/后缀增量运算符

时间:2010-07-05 17:27:11

标签: c++ increment return-by-reference

我想确保我理解按值传递和正确传递。特别是,我正在查看对象的增量++运算符的前缀/后缀版本。

我们假设我们有以下课程X

class X{
private:
    int i;
public:
 X(){i=0;}
 X& operator ++ (){ ++i; return *this; } //prefix increment

 X operator ++ (int unused){ //postfix increment
  X ret(*this);
  i++;
  return ret;
 }

 operator int(){ return i; } //int cast
};

首先,我是否正确实现了前缀/后缀增量运算符?

第二,与前缀运算符相比,后缀运算符的内存效率如何?具体来说,当使用每个版本的运算符时,会创建多少X个对象副本?

确切地说,通过引用返回和按值返回会发生什么可能有助于我理解。


编辑:例如,使用以下代码...

X a;
X b=a++;

... a和b现在是别名吗?

3 个答案:

答案 0 :(得分:18)

在后缀增量中调用对象本身的前缀增量更为惯用:

X operator++(int)
{
    X copy(*this);
    ++*this;         // call the prefix increment
    return copy;
}

因此,递增X对象的逻辑仅包含在前缀版本中。

答案 1 :(得分:17)

这是一个正确的实现。通常情况下,后缀运算符的性能会更差,因为您必须在执行增量之前创建另一个副本(这就是为什么我习惯于始终使用前缀,除非我需要其他内容)。

通过引用返回,您将返回对当前对象的l值引用。编译器通常会通过返回当前对象的地址来实现它。这意味着返回对象就像返回一个数字一样简单。

但是,按值返回,必须完成复制。这意味着在返回期间(而不仅仅是地址)复制更多信息以及要调用的复制构造函数。这就是你的表现受到影响的地方。

您的实施效率与典型实施相当。

编辑: 关于你的附录,不,它们不是别名。您已创建两个单独的对象。当您按值返回时(以及从后缀增量运算符中创建新对象时),此新对象将放置在不同的内存位置。

但是,在以下代码中,a和b 别名:

 int a = 0;
 int& b = ++a;

b是引用a。

的地址

答案 2 :(得分:2)

您的操作员已正确实施。

在前缀运算符中,不会生成X的副本。

在后缀运算符中,一个副本用于ret,而可能另一个副本在从函数返回时生成,但所有编译器都将忽略此副本。