6

I am creating a map just for learning purpose to store some key value pairs. If I print the second field of map using begin() function I am able to print the second field of map but when I try to do same with last element of map using end() it is not able to print the second field. Below is my code:

#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;

}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Paul Sen
  • 526
  • 1
  • 4
  • 20
  • 3
    for STL Containers, ".end()" yields an iterator to the "1-past-the-end-element" see also: http://stackoverflow.com/questions/15252002/what-is-the-past-the-end-iterator-in-stl-c – user2950911 Jul 09 '15 at 12:36

5 Answers5

6

Dereferencing end() is undefined behavior as end() returns an iterator to 1 past the end of the map. If you want the last element then you can use

p = --arr.end();

You cannot use

p = arr.rbegin()

As you cannot assign a reverse iterator to a forward iterator(live example). If you want to use rbegin() then you have to create a reverse iterator.

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

// or

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

Or you can convert it to a forward iterator using this answer by visitor

As always you should check to make sure that you have a valid iterator. If the container is empty begin() == end() and dereferencing either is undefined behavior.

Source: http://en.cppreference.com/w/cpp/container/map/end

Community
  • 1
  • 1
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
3

To print the last element, use reverse iterator:

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 will return the iterator to one past last element and dereferencing it is undefined behavior.

From std::map::end at en.cppreference

Returns an iterator to the element following the last element of the container. This element acts as a placeholder; attempting to access it results in undefined behavior.

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
2

You can use --arr.end() or arr.rbegin().

arr.end() returns iterator to the element after the last element. This allows easier writing loops. This element is only for comparing. Dereferencing it is not allowed.

Piotr Siupa
  • 3,929
  • 2
  • 29
  • 65
1

std::SOMETHING.end() doesn't return the last element, it returns past-the-end element. Check the C++ documentation. In essence what you are doing is trying to deference undefined memory location.

XapaJIaMnu
  • 1,408
  • 3
  • 12
  • 28
1

As already pointed out in other posts end() is an iterator one position past the last element in the map. Thus you should not try to get its fields. To get the last element you can use rbegin().

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176