实现C ++ postfix增量运算符

时间:2010-12-03 16:32:41

标签: c++ operator-overloading post-increment postfix-operator

我编译了以下示例:

#include <iostream>
#include <iterator>
using namespace std;

class myiterator : public iterator<input_iterator_tag, int>
{
  int* p;
public:
  myiterator(int* x) :p(x) {}
  myiterator(const myiterator& mit) : p(mit.p) {}
  myiterator& operator++() {++p;return *this;}
  myiterator& operator++(int) {myiterator tmp(*this); operator++(); return tmp;}
  bool operator==(const myiterator& rhs) {return p==rhs.p;}
  bool operator!=(const myiterator& rhs) {return p!=rhs.p;}
  int& operator*() {return *p;}
};

int main () {
  int numbers[]={10,20,30,40,50};
  myiterator beginning(numbers);
  myiterator end(numbers+5);
  for (myiterator it=beginning; it!=end; it++)
      cout << *it << " ";
  cout << endl;

  return 0;
}

来自cplusplus.com/reference,我收到编译器警告:

iterator.cpp: In member function 'myiterator& myiterator::operator++(int)':
iterator.cpp:13: warning: reference to local variable 'tmp' returned

这里有什么问题?后缀签名应该是myiterator operator++(int),即按值返回吗?

是否在某处定义了后缀签名在STL迭代器上应该是什么样的?

4 个答案:

答案 0 :(得分:5)

  

是否在某处定义了后缀签名在STL迭代器上应该是什么样的?

标准。

标准规定了这些事情。在此操作的情况下,标准基本上表示“您必须返回可转换为const X&”的内容,其中X是迭代器。在实践中,这意味着如果适用于您(它没有),或者按值返回,您可以通过引用返回。

见24.1.3 / 1

答案 1 :(得分:3)

您不希望返回引用:通过执行此操作,您将返回对函数的引用,该函数在函数返回时不再存在。您所需要的只是:

myiterator operator++(int) {myiterator tmp(*this); operator++(); return tmp;}

答案 2 :(得分:2)

这一行:

myiterator& operator++(int) {myiterator tmp(*this); operator++(); return tmp;}

应该是:

myiterator  operator++(int) {myiterator tmp(*this); operator++(); return tmp;}
//      ^^^^ Not return by reference.
//           Don't worry the cost is practically nothing for your class
//           And will probably be optimized into copying the pointer back.

作为旁注:

您实际上并不需要复制构造函数:

myiterator(const myiterator& mit) : p(mit.p) {}

编译器生成的版本将完美运行(由于您不拥有类所包含的RAW指针,因此三/四的规则不适用。)

您的比较运算符可能应该标记为const,我个人更喜欢根据==运算符定义!=运算符,让编译器优化掉任何不合理(尽管这只是个人的事情)。

bool operator==(const myiterator& rhs) const {return p==rhs.p;}
bool operator!=(const myiterator& rhs) const {return !(*this == rhs);}
                            //        ^^^^^^^ Added const

运营商*应该有两个版本。普通版和常量版。

int&       operator*()       {return *p;}
int const& operator*() const {return *p;}

作为最后一点:一个指针本身一个迭代器。所以你实际上不需要包装指针来使它们成为迭代器,它们将作为迭代器正确运行(而不仅仅是输入迭代器而是随机访问迭代器)。

答案 3 :(得分:0)

您将返回对方法退出时被销毁的变量的引用。编译器警告你这样做的后果。当调用者接收到引用时,它引用的变量不再存在。