1

I'm practicing std::deque, specifically iterators

I tested the end iterator. like this:

    std::deque<const char*> wup {"how","are","you","doing","today?"};
    std::deque<const char*>::iterator it = wup.end();

Then, I want to print it , and I know that the end iterator is empty.

enter image description here

Then I try to use 2 cout statements to print the content of it: one of them before --it and another after --it

But if I write a cout before --it, the last cout does not appear in the output.

Something like this:

std::deque<const char*> wup {"how","are","you","doing","today?"};
std::deque<const char*>::iterator it = wup.end();
std::cout<<"Before --it: "<<*it<<std::endl;// okay, it works good | and finishes console
--it;
std::cout<<"After --it: "<<*it<<std::endl;// I do not know why it does not appear.

Output:

    Before --it:
    Process returned 0 (0x0)   execution time : 0.010 s
    Press ENTER to continue.

Where did I make a mistake ?
if dereferencing an iterator is wrong ...
why this case, cuts the output-stream without any exception
Thanks a lot. tested on:
OS: Ubuntu 16.01
compiler: g++ version: 5.3.1
IDE: code::blocks 16.01


Edit: I found this note in /reference/en/cpp/container/map/erase.html :

The iterator pos must be valid and dereferenceable. Thus the end() iterator (which is valid, but is not dereferencable) cannot be used as a value for pos.

I think this is real reason for, why ... .

my native language is not English, so excuse me, if you see some mistake

Shakiba Moshiri
  • 21,040
  • 2
  • 34
  • 44
  • 8
    You cannot dereference the end iterator. Using it is undefined behavior. – NathanOliver Jun 28 '16 at 17:51
  • @NathanOliver Does it is wrong everywhere ? I mean in `array` and ... another container .... – Shakiba Moshiri Jun 28 '16 at 17:53
  • 1
    If you want to go backwards, use rbegin and rend (the same as you would use begin and end) – Kenny Ostrom Jun 28 '16 at 17:57
  • 1
    related: http://stackoverflow.com/questions/5322104/how-portable-is-end-iterator-decrement – 463035818_is_not_an_ai Jun 28 '16 at 17:58
  • 1
    When you say you know the end iterator is empty, it makes it sound like you expected it to return an empty string, which is completely wrong. – Kenny Ostrom Jun 28 '16 at 17:59
  • @KennyOstrom thanks but I know this. I want to know why this case, cuts the output-stream without any exception – Shakiba Moshiri Jun 28 '16 at 17:59
  • @tobi303 thank you so much – Shakiba Moshiri Jun 28 '16 at 18:01
  • You can only attempt to dereference the end() iterator in the case of a grievious logical error. Actually checking for that and giving you special notifications would involve adding significant computation to every piece of code anyone ever wrote, and that's antithetical to the c++ language design goals. – Kenny Ostrom Jun 28 '16 at 18:02
  • @KennyOstrom Besides, I expect an exception. thank you – Shakiba Moshiri Jun 28 '16 at 18:08
  • 1
    I was just trying to say it can't give you an exception unless it knows about it. That would require that the standard library spends extra cpu and memory to check the iterator, every time you access it. The actual answer to your question was in the first comment. You screwed up with "it=wup.end(); cout << *it;" – Kenny Ostrom Jun 28 '16 at 18:12
  • 1
    @k-five: Ultimately there's no exception because C++ allows you to shoot yourself in the foot. Performing a range check each time is "slow". You're more likely to get a segfault, because many iterators are ultimately wrappers to pointers on the heap, and you may end up dereferencing a pointer to a protected memory location. However, undefined behavior is undefined, so the implementor is free to actually throw an exception, or order a pizza, whatever they want. – AndyG Jun 28 '16 at 18:16
  • @AndyG C lets you shot yourself in the foot. C++ lets you blow your whole leg off ;) – NathanOliver Jun 28 '16 at 18:21
  • @AndyG Okay :) I understood : undefined behavior is undefined – Shakiba Moshiri Jun 28 '16 at 18:25

1 Answers1

2

Where did i make a mistake?

This line:

std::cout<<"Before --it: "<<*it<<std::endl;

is de-referencing an iterator that points past the end of the container which is undefined behavior.

Why this case, cuts the output-stream without any exception?

This question comes in 2 parts:

  1. Why does it cut the output stream? Because undefined behavior is undefined. You don't know what will happen. There is plenty of information around about this: http://en.cppreference.com/w/cpp/language/ub

  2. Why no exception? In order to provide an exception to everything that might cause UB, c++ would have to check every de-reference which would be computationally expensive for very little gain. It is up to the user to use the iterator interface correctly. This is the same in the following example:


 int a[5];
 a[6] = 10; // Why does c++ allow this when it is clearly a mistake? Because the user is 
            // responsible for writing good code, not the compiler, and certainly
            // not the run-time exception handler.  
Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175