我正在阅读“SAMS在21天内自学C ++”,我遇到了一个我似乎无法理解的例子:
#include<iostream>
using namespace std;
class Counter
{
public:
Counter() {itsVal=0;}
const Counter& operator++ ();
int GetItsVal() {return itsVal;}
private:
int itsVal;
};
const Counter& Counter::operator++()
{
++itsVal;
return *this;
}
int main()
{
Counter i;
Counter a = ++i;
cout << "a: " << a.GetItsVal() << " i: " << i.GetItsVal() << endl;
++a;
cout << "a: " << a.GetItsVal() << " i: " << i.GetItsVal() << endl;
}
为什么会有“&amp;”在++运算符的声明中?我理解这意味着++运算符的返回类型是一个引用,但它似乎不是对i的引用(因为递增a不会增加i)。我注意到如果删除“&amp;”,代码会返回相同的结果,但可能效率不高。
答案 0 :(得分:5)
在C ++中,当您创建引用时,它是原始对象的代理:
int i = 0;
int& a = i;
++i;
std::cout << i << " " << a << "\n"; // prints '1 1'
++a;
std::cout << i << " " << a << "\n"; // prints '2 2'
现在,在你的情况下:
operator++
返回对当前对象的引用Counter a = ++i;
创建了一个新对象(&
之后没有Counter
),初始化为对i
的引用的副本如果您希望a
引用i
,则需要更改其声明:
Counter& a = ++i;
^
这将无法编译思维,因为Counter::operator++
的返回值为Counter const&
:您需要删除const
这里operator++
非惯用的Counter& Counter::operator++() { ++itsVal; return *this; }
因此:
{{1}}
答案 1 :(得分:2)
许多函数通常会观察其返回值和一般行为的模式,使您可以轻松自然地使用它们。
预增量和预减量运算符在执行链接任务后总是返回对象的引用:
Counter& Counter::operator++()
Counter& Counter::operator--()
虽然后递增和后递减运算符不返回任何值,或者包含旧值的临时值用于容易复制的值类型:
Counter Counter::operator++(int)
Counter Counter::operator--(int)
或者
void Counter::operator++(int)
void Counter::operator--(int)
在你的例子中,似乎有人没有遵循惯例。
答案 2 :(得分:0)
为了让您轻松理解这一点,请考虑赋值运算符重载。
计数器&安培; operator =(const Counter&amp; RHS);
反击a(10),b(20),c,d;
现在,
c = d = a是可能的。当您返回某些内容作为参考时,该重载调用可以用作R值。
答案 3 :(得分:0)
考虑一下:
void someFunction(const Counter& c);
void someFunction(Counter& c);
...
{
Counter myCount = makeACounter();
while(myCount.stillCounting()) {
someFunction(++myCounter);
}
}
someFunction()
需要参考,所以你要做的最后一件事就是复制myCounter,因为它可能效率低下。此外,如果选择someFunction的非const变体(在这种情况下将是这样),传递副本在逻辑上是错误的,因为someFunction可以合法地修改其参数的状态,并且您期望看到函数返回时更改myCounter。
由于上述情况(以及其他情况),operator++
应该返回*this
的非const引用(你刚刚修改了* this,所以它不能是const吗? )
因此方法签名应该是:
Counter& operator++ ();