title: Why is undefined behavior allowed in the STL?
body: <p>By default, the "underlying container" of an <code>std::stack</code> is an <code>std::deque</code>. Therefore anything that is undefined behavior for a <code>std::deque</code> is undefined behavior for a <code>std::stack</code>. <a href="http://en.cppreference.com/w/cpp/container/stack/top" rel="noreferrer">cppreference</a> and other sites use the terminology "effectively" when describing the behavior of member functions. I take this to mean that it is for all intents and purposes. So therefore, calling <code>top()</code> and <code>pop()</code> is equivalent to calling <code>back()</code> and <code>pop_back()</code>, and calling these on an empty container is undefined behavior. </p>
  
  <p>From my understanding, the reason why it's undefined behavior is to preserve the no-throw guarantee. My reasoning is that <code>operator[]</code> for <code>std::vector</code> has a no-throw guarantee and is undefined behavior if container size is greater than N, but <code>at()</code> has a strong guarantee, and throws <code>std::out_of_range</code> if n is out of bounds.</p>
  
  <p>So my question is, what is the rationale behind some things having possibly undefined behavior and having a no throw guarantee versus having a strong guarantee but throwing an exception instead?</p>