Вопрос стека C ++ STL: почему pop () не генерирует исключение, если стек пуст? - PullRequest
20 голосов
/ 04 февраля 2011

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

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

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

Ответы [ 6 ]

12 голосов
/ 04 февраля 2011

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

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

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

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

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

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

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

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

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

Я думаю, что можно спросить, почему top() не вызывает исключение , или , можно спросить, почему pop() не возвращает верхний элемент. Если pop ничего не возвращает, создание исключения не имеет смысла (в мире C ++) - утверждение о том, что оно не генерирует исключение «из-за затрат на исключение во время выполнения», как, по-видимому, подразумевают другие ответы это - ИМХО - упущение.

8 голосов
/ 04 февраля 2011

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

5 голосов
/ 04 февраля 2011

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

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

3 голосов
/ 04 февраля 2011

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

2 голосов
/ 04 февраля 2011

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

1 голос
/ 04 февраля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...