6

次の例をコンパイルしました。

#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

4 に答える 4

5

STLイテレータで後置署名がどのように見えるべきか定義された場所はありますか?

標準。

規格はそのようなことを規定しています。この操作の場合、標準では基本的にconst X&「変換可能なものを返さなければならない」と書かれXています。実際には、これは、それが当てはまる場合 (当てはまらない場合) に参照によって返すことも、値によって返すこともできることを意味します。

24.1.3/1 参照

于 2010-12-03T16:45:02.223 に答える
4

参照を返したくありません。そうすることで、関数が返されるまでに存在しなくなった変数への参照を返します。あなたに必要なのは:

myiterator operator++(int) {myiterator tmp(*this); operator++(); return tmp;}
于 2010-12-03T16:35:02.533 に答える
3

この行:

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 ポインターを所有していないため、3/4 の規則は適用されません)。

比較演算子はおそらく const としてマークする必要があります。個人的には、== 演算子の観点から != 演算子を定義し、コンパイラに非効率性を最適化させることを好みます (ただし、これは個人的なことです)。

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

演算子 * には、おそらく 2 つのバージョンが必要です。通常バージョンと const バージョン。

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

最後の注意として: ポインター自体イテレーターです。したがって、ポインターをイテレーターにするために実際にラップする必要はありません。イテレーターとして正しく動作します (入力イテレーターだけでなく、ランダム アクセス イテレーターでもあります)。

于 2010-12-03T16:42:18.870 に答える
0

メソッドの終了時に破棄される変数への参照を返します。コンパイラは、この結果について警告しています。参照が呼び出し元によって受信されるまでに、参照する変数は存在しなくなります。

于 2010-12-03T16:35:35.830 に答える