LINUX.ORG.RU

Почему я должен платить за проверки в push

Потому как push() в stack с size() == capacity() абсолютно legit operation, в отличие от.

а pop для пустого стека приводит его в неконсистентное состояние?

Нет. Это UB. Говорить про «неконсистентное состояние» в этом случае вообще неуместно. Если повезёт - упадёте в корку поблизости.

bugfixer ★★★★★
()

А зачем push проверять capacity стэка? Имеется ввиду, что он работает как vector и на самом деле capacity обычно больше количества элементов? Тогда логично проверить, есть ли место перед добавлением и увеличить размер на несколько элементов, если нужно.

А при удалении нужно самому проверить сначала размер. Что не так то?

grem ★★★★★
()

Capacity или size? pop точно не должен проверять capacity.

При типичном применении pop ты и так сам делаешь проверку. И дублировать её внутри нет никакого смысла.

while (!stack.empty())
{
    std::cout << mystack.top() << std::endl;
    stack.pop();
}
ox55ff ★★★★★
()
Ответ на: комментарий от snizovtsev

Зачем он вообще нужен? Используй напрямую vector или deque – их API вызубрены всеми, и код читается легче.

Вот видите - Вы по сути сами ответили на свой вопрос предоставив выбор: в подавляющем числе случаев std::deque<> будет лучше для stack access patterns. Но, должен признать - адаптеры в реальной жизни использовать приходится крайне редко, так что в чём-то Вы правы.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

в подавляющем числе случаев std::deque<> будет лучше для stack access patterns

Кмк std::vector лучше – он предсказуемо выделяет память, и почти всегда можно заранее рассчитать нужный объём и вставить reserve. А у std::deque блоки непонятно какого размера, лишние указатели, потеря random access.

Я бы сказал, что на практике в 99% достаточно 4х cтруктур – std::vector, absl::flat_hash_map, absl::btree_map и intrusive list.

snizovtsev ★★★★★
()
Последнее исправление: snizovtsev (всего исправлений: 4)

Почему я должен платить за проверки в push, а pop для пустого стека приводит его в неконсистентное состояние?

А в какое состояние должно приводить pop для пустого стека?

wandrien ★★
()

Поберегите бисер, это ж тролль, на пике ожидается come out в адрес какой-нибудь скриптухи и предание анафеме цпп + парочка мощных проклятий.

kvpfs ★★
()
Ответ на: комментарий от untitl3d

Потому что перед тем, как спрашивать, нужно подумать головой.

Пусть .pop возвращает… а что, собственно?

Если возвращать T, то на каждый .pop, даже немедленно отбрасывающий результат, необходимо произвести move (потенциально выбрасывающее исключение), а то и копирование объекта.

Если возвращать T*, то кто владеет указателем? Как его нужно освободить? delete, free, какой-то аллокатор? Что делать, если queue внутри использует deque, и элемент хранился в одном блоке памяти с другими элементами? Переаллоцировать?

Частично проблемы указателя снимаются заворачиванием в искусственный тип, а-ля queue_element, но тогда и вовсе невозможно использовать queue как адаптер.

Наконец, а что делать, если очередь пуста? Оборачивать в optional? Еще более дорого, чем просто T. Выбрасывать исключение? Тоже дорого.

И так далее.

А подход с .front и .pop оптимален, пользователь сам делает move/copy при необходимости сохранить объект в целости и сохранности, либо использует по месту.

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 1)
Ответ на: комментарий от untitl3d

Почему front() может возвращать, а pop() нет?

.front возвращает ссылку. .pop ссылку возвращать не может по причинам, обрисованным выше.

Почему, блджад, каждый другой яп возвращает из pop()

Потому что это в большинстве своем языки с ГЦ. Проблемой в С++ это не является, это просто в большинстве случаев бесполезный жир.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

То, что возвращает pop() можно игнорировать. В таком случае компилятор не делал бы ничего. Если возврат pop() присваивается, можно делать front(); pop() под капотом. Но у нас же особый путь и миллион проблем, так?

untitl3d
()
Ответ на: комментарий от untitl3d

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

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

потому front() и pop() - это примитивные операции, эффективность которых максимальна. а вот из них уже можно нагородить свои функции. отнаследуйся от коллекции и городи.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

Не знаю, как там лучшие умы планеты, а я в своем бездарном коде в 99% случаев делаю pop() после front() и иногда этот сраный поп забываю =\

Свои коллекции писать не вижу смысла из-за этого. Куда эффективнее ворчать на форуме.

untitl3d
()
Последнее исправление: untitl3d (всего исправлений: 1)
Ответ на: комментарий от untitl3d

Дело в том, что сам по себе поп - ничего особенного, пустая трата службы и елея. А поп на фронте - совсем другое дело, сразу жизнь становится более осмысленной.

seiken ★★★★★
()