По умолчанию "базовый контейнер" std::stack - это std::deque. Поэтому все, что есть undefined поведение для std::deque, - это поведение undefined для std::stack. cppreference, а другие сайты используют терминологию "эффективно" при описании поведения функций-членов. Я полагаю, это означает, что это предназначено для всех целей и целей. Таким образом, вызов top() и pop() эквивалентен вызовам back() и pop_back(), а вызов их в пустом контейнере - это поведение undefined.
По моему мнению, причина, по которой это поведение undefined заключается в том, чтобы сохранить гарантию отсутствия броска. Мое рассуждение состоит в том, что operator[] для std::vector имеет гарантию отсутствия броска и имеет значение undefined, если размер контейнера больше N, но at() имеет сильную гарантию и бросает std::out_of_range, если n не входит в границы.
Итак, мой вопрос в том, что является причиной некоторых вещей, которые могут иметь поведение undefined и не имеют никакой гарантии броска по сравнению с сильной гарантией, но вместо этого выбрасывают исключение?