littleZ
littleZ

Reputation: 71

About iterator of containers

I do not know, why does it output 1024?

vector<int> default_container = { 1,2,3,4,5,6,7,78,8,1024 };
cout << *default_container.end() << endl; // 0
default_container.pop_back();

for (auto it : default_container) 
{
    cout << it << ",";
}
cout << endl;

cout << *default_container.end() << endl;   // 1024 why?why?why?why?
cout << *--default_container.end() << endl; // 8

Upvotes: 4

Views: 165

Answers (2)

JeJo
JeJo

Reputation: 32722

Your program has Undefined behavior!

You are de-referencing the end iterator, at the lines

cout << *default_container.end() << endl;
...
cout << *default_container.end() << endl;

which gives you undefined behavior. Form cppreference.com the std::vector::end, std::vector::cend

enter image description here

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

Means, anything can be happened; therefore you shouldn't be relaying on its result and should not be doing it!


That being said, it looks like that you want to access the last element in the vector. If that the case, for a non-empty vector you have multiple other (safe) choices:

  1. Using std::vector::back

    // prints first 8 from last; due to "default_container.pop_back()"  
    std::cout << default_container.back(); 
    
  2. Using std::prev

    #include <iterator>
    
    // prints first 8 from last; due to "default_container.pop_back()"  
    std::cout << *std::prev(default_container.end()); 
    
  3. Using reverse iterator std::rbegin

    // prints first 8 from last; due to "default_container.pop_back()"  
    std::cout << *std::rbegin(default_container);
    

As a side note, see: Why is "using namespace std;" considered bad practice?

Upvotes: 13

Pepijn Kramer
Pepijn Kramer

Reputation: 12849

The previous answer says it all. In other words you're not supposed to use end() for anything else then comparing an iterator to. Eg.

for (auto it = container.begin(); it < container.end(); ++it)

Also note that your line for (auto it : default_container) isn't creating an iterator but literally an int.

// foreach value in container
for(int value : default_container) 
{
  cout << value;
}

note that if you're not planning to change the values you're iterating over you can use this :

for(const auto value : default_container) {}

or if your containter contains objects (instance of classes)

for(const auto& object : container) {}

Upvotes: 0

Related Questions