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