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) i.e. return by value?

Есть ли какие-то определения, как должна выглядеть подпись postfix на итераторах 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. Я действительно ищу определение оператора приращения postfix для итераторов 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 

Оператор * должен иметь две версии. Нормальная и константная версии.

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

В последней ноты: указатель сам по себе Является итератор. Так что на самом деле вам не нужно обтекать указатели, чтобы сделать их итераторами, они будут корректно вести себя как итераторы (а не только итераторы ввода, но итераторы с произвольным доступом).

 Смежные вопросы

  • Нет связанных вопросов^_^