Невозможно получить второе поле карты с помощью end()

Я создаю карту только для целей обучения, чтобы сохранить несколько пар ключ-значение. Если я печатаю второе поле карты, используя begin() Функция Я могу напечатать второе поле карты, но когда я пытаюсь сделать то же самое с последним элементом карты, используя end() оно не может напечатать второе поле. Ниже мой код:

#include <iostream>
#include <cstdlib>
#include <map>
#include <string>
#include <stdio.h>


using namespace std;

map<int,std::string> arr;

map<int,std::string>::iterator p;

int main(int argc, char** argv) {

    arr[1] = "Hello";   
    arr[2] = "Hi";   
    arr[3] = "how";   
    arr[4] = "are";
    arr[5] = "you"; 

    p = arr.begin();
    printf("%s\n",p->second.c_str()); 

    p =  arr.end();
    printf("%s\n",p->second.c_str());

    return 0;

}

5 ответов

Решение

Чтобы напечатать последний элемент, используйте обратный итератор:

map< int,std::string>::reverse_iterator p;
p = arr.rbegin();
if( p != arr.rend() ) {
  // Do whatever with, it points to the last element
} else {
  // map is empty
}

std::map::end вернет итератор к последнему последнему элементу, и разыменование будет неопределенным поведением.

От std::map::end на en.cppreference

Возвращает итератор для элемента, следующего за последним элементом контейнера. Этот элемент действует как заполнитель; попытка доступа к нему приводит к неопределенному поведению.

Разыменование end() неопределенное поведение как end() возвращает итератор на 1 после конца карты. Если вы хотите последний элемент, то вы можете использовать

p = --arr.end();

Вы не можете использовать

p = arr.rbegin()

Поскольку вы не можете назначить обратный итератор прямому итератору ( живой пример). Если вы хотите использовать rbegin() тогда вы должны создать обратный итератор.

map<int,std::string>::reverse_iterator rit;
rit = arr.rbegin();

// or

auto rit = arr.rebegin();  //C++11 or higher required for this 

Или вы можете преобразовать его в прямой итератор, используя этот ответ от visitor

Как всегда, вы должны проверить, чтобы убедиться, что у вас есть действительный итератор. Если контейнер пуст begin() == end() и разыменование является либо неопределенным поведением.

Источник: http://en.cppreference.com/w/cpp/container/map/end

Ты можешь использовать --arr.end() или же arr.rbegin(),

arr.end() возвращает итератор в элемент после последнего элемента. Это позволяет легче писать циклы. Этот элемент только для сравнения. Разыменование не допускается.

Как уже указывалось в других постах end() является итератором на одну позицию за последним элементом на карте. Таким образом, вы не должны пытаться получить его поля. Чтобы получить последний элемент, который вы можете использовать rbegin(),

std::SOMETHING.end() не возвращает последний элемент, он возвращает последний элемент. Проверьте документацию C++. По сути, то, что вы делаете, пытается определить неопределенное место в памяти.

Другие вопросы по тегам