C++ 前缀/后缀增量运算符

C++ 前缀/后缀增量运算符,c++,increment,return-by-reference,C++,Increment,Return By Reference,我想确保我正确理解传递值和传递引用。特别是,我正在研究对象的increment++操作符的前缀/后缀版本 假设我们有以下类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++;

我想确保我正确理解传递值和传递引用。特别是,我正在研究对象的increment
++
操作符的前缀/后缀版本

假设我们有以下类
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现在是别名吗?

这是一个正确的实现。通常,后缀运算符的性能会更差,因为在执行增量之前必须创建另一个副本(这就是为什么我养成了总是使用前缀的习惯,除非我需要其他东西)

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

但是,如果按值返回,则必须进行复制。这意味着在返回过程中要复制更多的信息(而不仅仅是一个地址)以及要调用的复制构造函数。这就是你的表演热播的地方

您的实现的效率看起来与典型的实现相当

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

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


b是引用a的地址。

您的运算符实现正确

在前缀运算符中,不复制X


在后缀运算符中,为ret创建一个副本,从函数返回时可能会创建另一个副本,但所有编译器都将省略此副本。

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

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

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

一般来说是正确的,以可能的返回值优化()为模。是的,这使我免于发布相同的更正<代码>+1来自我。不需要在后缀运算符中后缀增量
i
。事实上,我会按照和调用前缀版本。在我看来,这确实比重新实现增量更惯用(尽管这里的实现很简单)。然后去掉隐式转换操作符。否则你会受伤的。(我第三次也是最后一次编写隐式转换运算符是在2001年,一两年后,我发现它导致了一些细微的错误,并将其删除—就像.BTDTGTLS之前的所有错误一样。)
X operator++(int)
{
    X copy(*this);
    ++*this;         // call the prefix increment
    return copy;
}