Подтвердить что ты не робот

Вопрос стека ST ++: почему pop() не генерирует исключение, если стек пуст?

Почему std:: stack:: pop() не генерирует исключение, если стек пуст и нечего делать?

(Я разрабатываю специализированный Stack для своего собственного кода и хотел бы знать компромиссы с этим подходом (который требует, чтобы один вручную проверял, является ли стек пустым) против бросания исключения.

Мое предположение заключается в том, что хотя С++ поддерживает обработку исключений, он имеет небольшие накладные расходы во время выполнения, и поэтому для максимальной производительности было принято решение не генерировать исключение в std:: stack:: pop).

4b9b3361

Ответ 1

Вы правы. Стандарт С++ всегда предпочитает безопасность. Но могут быть реализации STL, которые включают проверки диапазона отладки.

Ответ 2

Я бы сказал, что причина pop() не должна генерировать исключение, не имеет ничего общего с эффективностью или производительностью, но с - исключениями.

Как утверждается в другом месте:

  • Объяснение SGI: http://www.sgi.com/tech/stl/stack.htmlИнтересно, почему pop() возвращает void, а не value_type. То есть, почему нужно использовать top() и pop() для изучить и удалить верхний элемент, вместо объединения двух в функция одного члена? Фактически, там является хорошей причиной для этого дизайна. Если pop() вернул верхний элемент, он должен был бы чем по ссылке: возврат по ссылке создаст висячий указатель. Возврат по значению, однако, равен неэффективен: он включает по крайней мере один вызов избыточного экземпляра копии. поскольку невозможно, чтобы pop() возвратил так, чтобы быть как эффективный и правильный, больше разумный, чтобы он не возвращал никакой ценности при всех и требовать от клиентов использования top() для проверки значения вверху стека.

  • std:: stack <T> является шаблоном. Если pop() вернул верхний элемент, он должен был бы чем по ссылке в соответствии с вышеизложенным объяснение. Это значит, у вызывающего сторона должна быть скопирована в другой T тип объекта. Это включает в себя копию назначение конструктора или копии вызов оператора. Что делать, если этот тип T достаточно сложный, и он бросает исключение при создании копии или назначение копии? В этом случае rvalue, т.е. верхняя часть стека (возвращается по значению) просто теряется, и есть нет другого способа получить его из стек, поскольку операция pop pop стека успешно завершено!

Как только мы заключаем, что pop не должен возвращать элемент, который он всплывает, и поэтому его интерфейс фиксируется как void pop(), он - это мое мнение - больше не имеет смысла предписывать, что происходит, когда pop() вызывается на пустой стек.

Обратите внимание, что для стандартного требования требуется !empty() как предварительное условие для вызова pop().

UncleBens (в комментариях), безусловно, имеет в виду, что не проверять предварительные условия во время выполнения (который никогда не предписывается С++ std AFAIK) имеет определенный запах производительности. Однако, чтобы процитировать часть оригинального вопроса: (внимание мое)

(Я проектирую специализированный Stack for мой собственный код и хотел бы знать компромисс с этим подходом (который требует, чтобы стек пуст) против бросания исключение.

Я буду утверждать, что тот факт, что pop() не возвращает ничего, делает вопрос спорным. Он (IMHO) просто не имеет смысла заставить pop() проверять, пуст ли пуст, когда мы действительно ничего не получаем от него (т.е. Если стек будет пустым pop() может просто быть noop, который (по общему признанию) не предписан Std также).

Я думаю, можно спросить, почему top() не генерирует исключение, или можно спросить, почему pop() не возвращает верхний элемент. Если pop ничего не возвращает, бросание исключения не имеет смысла (в мире С++) - утверждая, что он не генерирует исключение "из-за затрат времени на выполнение исключений", как, например, подразумевают другие ответы is - IMHO - отсутствует точка.

Ответ 3

Как почти все функции на С++, они разработаны вокруг концепции, что вы не платите за то, что вы не используете. Не все среды поддерживают исключения, традиционно и, самое главное, разработку игр.

Таким образом, принудительное использование исключений, если вы используете std:: stack, будет не соответствовать одному из принципов проектирования. Вы хотите иметь возможность использовать стек, даже если исключения отключены.

Ответ 4

Я думаю, что стоит упомянуть, что pop() разрешено бросать, если стек пуст - ему просто не требуется. В вашем стеке вы могли бы assert, что стек не был пустым, и это было бы прекрасно (pop в пустом стеке, похоже, дает UB, поэтому вы можете делать все, что захотите, действительно).

Ответ 5

Производительность в стороне, я не думаю, что выскакивание из пустого стека является исключительным сценарием - поэтому я бы тоже выбрал там.

Ответ 6

исключения являются необязательными, и STL хочет быть доступным повсюду. думаю, встроенные системы: много кода на С++, отсутствие поддержки исключений из времени выполнения.