2011-10-26 55 views
0

在C++中,无论我在网上看到后缀递增运算符声明的例子,它总是声明为C++后缀递增运算符的常量返回类型

T& operator++(int); 

,我相信这是一个后缀的正确语法增量,不是吗?

问题是,每当我声明后缀增量时,我用const关键字声明返回类型,以便它变成左值。

请参见示例代码:

class AClass 
{ 
    int foo; 

public: 
    AClass(void) : foo(0) {}; 

    // Suffix increment operator 
    // Consider adding const to return type 
    /* const */ AClass operator++(int) 
    { 
     AClass cp(*this); 
     foo++; 
     return cp; 
    }; 

    // Prefix increment operator 
    AClass& operator++() 
    { 
     foo++; 
     return *this; 
    }; 
}; 

int main(int argc, const char* args[]) 
{ 
    /* This code would fail to compile. 
    int bar = 5; 
    (bar++)++; 
    */ 

    // Similarily, I would expect this to fail 
    // but it will succeed unless I use const return type. 
    AClass a; 
    (a++)++; 
} 

我从未有过这样一个常量声明的运营商的问题,我知道它已经救了我们的代码从一个笨拙的同事做了一个错误。所以,我的问题是:

  1. 是否有任何缺点这样的做法?这确实是一个好习惯吗?
  2. 什么是后缀运算符的真正正确的声明(我的意思是标准)?
  3. 如果这不是标准的规定,但已经是一个很好的做法,它不应该成为一个标准吗?

非常感谢您的回答!

+0

你的前缀运算符应该返回一个引用:'AClass&operator ++()' – avakar

+0

II不能想到任何理由修改该函数的返回结果....我认为你很好。 –

+0

谢谢,你是对的,已经纠正了这一点,但它并没有改变这个问题。 – Andrew

回答

6

后缀增量返回一个临时的,不是引用(这意味着你的第一个签名是错误的):

T& operator++() // prefix 
{ 
    this->increment(); 
    return *this; 
} 

T operator++(int) // suffix 
{ 
    // Almost always, you'll have this code: 
    T tmp(*this); ++(*this); return tmp; 
} 

有些人喜欢为const-资格后缀运算符的返回值,以避免编写类似的蠢事

(a++).modify_me(); 

不修改a(它适用modify_me到一个临时对象)。与

(++a).modify_me(); 

它增加a,然后修改它。

个人而言,我不认为这是必要的(因为您可能对modify_me的副作用感兴趣)。而且,在C++ 11中,您可能希望将所述临时值绑定到(非const)右值引用。 Const限定后缀运算符的返回类型会禁用这种可能性。

+2

+1:const rvalues不好。 – Puppy

+0

@DeadMG:完美地说。例如,看到另外一些很好的书籍,例如Numerical Recipes,它系统性地将r值参数限定为函数本质上是没有道理的。 –

+0

@Alexandre:原因是提问者说,允许内置运算符允许的表达式,并禁止它们禁止的表达式。这不是“没有理由”,只是有更好的理由去做相反的事情(在C++ 11中移动语义,但即使在C++ 03中也存在互换优化)。 –

1

我相信这是一个后缀增量的正确语法,是不是 呢?

如果通过“正确”,你的意思是“普遍的做法”,那么没有。如果你试图创建与整数后缀运算符一致的行为,那么它应该按值返回。

const T operator++(int); 

这是因为它会进行复制,然后递增,然后返回副本。由于副本是本地的,你绝对不想通过引用返回它。

您可以带走或离开的常量,但通过价值而不是参考的回报是必不可少的。