4

我整理了以下例子:實現C++後綴增量操作

#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迭代器上的樣子?

+0

cplusplus.com是有用的,但不是權威的。在這種情況下,它會傷害你。如果你看一下實際的STL代碼,你會發現迭代器經常被返回值,而cplusplus.com並沒有告訴你可以這樣做。 – 2010-12-03 16:39:28

+0

http://stackoverflow.com/questions/3181211/prefix-postfix-increment-operators – 2015-06-17 10:22:35

回答

5

是否有某處定義了postfix簽名在STL迭代器上的樣子?

該標準。

該標準規定了這樣的事情。在這種操作的情況下,標準基本上說「你必須返回可兌換爲const X&的東西」,其中X是迭代器。在實踐中,這意味着您可以通過引用返回(如果這適用於您(不))或按值返回。

請參閱24.1.3/1

3

您不想返回引用:通過這樣做,您將返回一個對該變量的引用,該變量在函數返回時不再存在。所有你需要的是:

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

+1這就是答案。我只補充說,錯誤消息告訴你到底是什麼問題,對給定錯誤的邏輯解決方案實際上是正確的答案。按價值返回東西,而不是參考。 – 2010-12-03 16:37:41

+0

我知道。那是來自cplusplus.com的代碼。我真的在尋找STL迭代器的後綴增量運算符的定義... – chris 2010-12-03 16:38:10

0

你正在返回一個變量的引用,當方法退出時它會被銷燬。編譯器正在警告你這樣做的後果。到調用者接收到引用時,它引用的變量不再存在。

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) {} 

編譯器生成版本on將完美地工作(因爲你不擁有你的類所包含的RAW指針,所以三/四的規則不適用)。

您的比較運算符應該被標記爲const,我個人更喜歡用==運算符來定義!=運算符,並讓編譯器優化掉任何無效(儘管這只是個人的事情)。

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

運算符*應該可能有兩個版本。一個正常和一個const版本。

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

作爲最後一個音符:本身一個指針的迭代器。所以你實際上不需要包裝指針來使它們成爲迭代器,它們將作爲迭代器正確運行(而不僅僅是輸入迭代器,而是隨機訪問迭代器)。