C++ rbegin изменить адрес reverse_iterator

У меня странная проблема в С++ с этим кодом:

mutex_type  list_mutex;
typedef list<char*> RQueue;
RQueue rQueue;
RQueue::reverse_iterator  rstart, rend, last;

  1  while(true) {
  2      LockMutex(list_mutex);
  3      rstart = rQueue.rbegin();
  4      rend   = rQueue.rend();
  5      while( (rstart != rend) && (rstart != last) ) {
  6           print *rstart;
  7      }
  8      last = rQueue.rbegin(); 
  9      UnlockMutex(list_mutex);
  10  }
  • rQueue - это очередь, в которой я итерирую в обратном порядке
  • rQueue может получать сообщения в любое время
  • Я добавил итератор last, чтобы избежать переделки с получением сообщения в строке 6
  • В строке 8 я сохраняю позицию, с которой я печатал сообщения, и я хочу печатать только те сообщения, которые новее последнего сообщения.

    Моя проблема: когда итерация завершена и в очередь добавляются новые сообщения, значение итератора last изменяется, становясь таким же, как значение итератора rstart, поэтому новые поступившие сообщения не печатаются в строке 6.

Я не знаю, почему last = rQueue.rbegin() изменяет свое значение при получении новых элементов после разблокировки очереди.

Спасибо.


person georgiana_e    schedule 08.11.2013    source источник
comment
Хотя этот вопрос на самом деле не является дубликатом, мой ответ там отвечает на вопрос, который у вас есть здесь.   -  person Benjamin Lindley    schedule 08.11.2013
comment
Не то чтобы оператор while будет означать то же самое, если вы удалите две трети круглых скобок.   -  person Pete Becker    schedule 08.11.2013


Ответы (1)


Если вы установите итератор на rbegin(), он всегда будет указывать на последний элемент списка. Если вы добавите еще один элемент сзади, итератор по-прежнему будет указывать на последний элемент (который теперь является новым). Он не изменится, он просто продолжает указывать на конец.

Я сделал этот тест:

list<const char *> my_list;
my_list.push_back("msg 1");

list<const char*>::reverse_iterator it = my_list.rbegin();

cout << "Iterator is " << *it << endl;

my_list.push_back("msg 2");
my_list.push_back("msg 3");
my_list.push_back("msg 4");

cout << "Iterator is " << *it << endl;

Эта программа дает вывод:

Iterator is msg 1
Iterator is msg 4

У меня есть другое решение, которое вы можете использовать, которое не использует обратный итератор. Вместо этого функция addMessage() обновляет read_pos до самого нового сообщения. Если read_pos не указывает на конец, он также не изменяется. Это позволяет printMessage() печатать все сообщения, которые были добавлены с момента последнего запуска.

Обратите внимание, что я тестировал это только без блокировки.

mutex_type  list_mutex;
typedef list<const char*> RQueue;
RQueue rQueue;

RQueue::iterator read_pos;

void addMessage(const char *message) {
    LockMutex(list_mutex);

    rQueue.push_back(message);

    if (rQueue.size() == 1) {
        read_pos = rQueue.begin();
    }
    else if (read_pos == rQueue.end()) {
        read_pos--;
    }

    UnlockMutex(list_mutex);
}

void printMessage() {
  RQueue::iterator prev_pos;

  while (true) {
    LockMutex(list_mutex);

    if (rQueue.size() == 0) {
          UnlockMutex(list_mutex);
          continue;
    }

    RQueue::iterator end = rQueue.end();
    while (read_pos != end) {
        cout << *read_pos << endl;
        read_pos++;
    }

    UnlockMutex(list_mutex);
  }
}
person Atle    schedule 08.11.2013