Почему должен появиться (), берут аргумент?

Быстрый фон
Я - Java-разработчик, который играл вокруг с C++ в мое свободное/скучающее время.

Предисловие
В C++ Вы часто видите, что поп берет аргумент ссылкой:

void pop(Item& removed);

Я понимаю, что хорошо "заполнить" параметр с тем, что Вы удалили. Это полностью имеет смысл мне. Таким образом, человек, который попросил удалять главный объект, может взглянуть на то, что было удалено.

Однако, если бы я должен был сделать это в Java, то я сделал бы что-то вроде этого:

Item pop() throws StackException;

Таким образом, после поп мы возвращаемся также: ПУСТОЙ УКАЗАТЕЛЬ в результате Объект или исключение был бы брошен.

Мой учебник C++ показывает мне пример выше, но я вижу много реализаций стека, берущих аргументы (stl стек, например).

Вопрос
Как нужно реализовать поп-функцию в C++?

Премия
Почему?

9
задан Jim Ferrans 3 May 2010 в 05:53
поделиться

5 ответов

Чтобы ответить на вопрос: вам не следует реализовывать функцию pop в C ++, поскольку она уже реализована в STL. Адаптер контейнера std :: stack предоставляет метод top для получения ссылки на верхний элемент в стеке и метод pop для удаления верхнего элемента. . Обратите внимание, что метод pop сам по себе не может использоваться для выполнения обоих действий, как вы просили.

Почему это должно быть сделано именно так?

  1. Безопасность исключений: Херб Саттер дает хорошее объяснение проблемы в GotW # 82 .
  2. Принцип единственной ответственности: также упоминается в GotW # 82. top берет на себя одну ответственность, а pop - другую.
  3. Не платите за то, что вам не нужно: Для некоторого кода может быть достаточно изучить верхний элемент, а затем вытащить его, даже не делая (потенциально дорогостоящую) копию элемента. (Это упоминается в документации SGI STL .)

Любой код, желающий получить копию элемента, может сделать это без дополнительных затрат:

Foo f(s.top());
s.pop();

Кроме того, это обсуждение может быть интересным.

Если вы собирались реализовать pop для возврата значения, не имеет большого значения, возвращаете ли вы его по значению или записываете его в выходной параметр. Большинство компиляторов реализуют RVO , который оптимизирует метод возврата по значению, чтобы он был столь же эффективным, как метод копирования в параметры. Просто имейте в виду, что любой из них, вероятно, будет менее эффективным, чем изучение объекта с помощью top () или front (), поскольку в этом случае копирование абсолютно не выполняется.

26
ответ дан 4 December 2019 в 07:14
поделиться

Единственная причина, по которой я могу использовать этот синтаксис в C ++:

void pop(Item& removed);

, - это если вы беспокоитесь о том, что будут иметь место ненужные копии.

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

На самом деле компиляторы C ++ очень хороши в копировании и почти всегда реализуют оптимизацию возвращаемого значения (часто даже при компиляции с отключенной оптимизацией), что делает вопрос спорным и может даже означать простой «возврат по значению» версия в некоторых случаях становится быстрее .

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

Дополнительная информация здесь

0
ответ дан 4 December 2019 в 07:14
поделиться

ИМО, хорошая сигнатура для эквивалента функции Java pop в C ++ будет выглядеть примерно так:

boost::optional<Item> pop();

Использование типов параметров - лучший способ вернуть то, что может быть, а может и нет.

0
ответ дан 4 December 2019 в 07:14
поделиться

Использование C ++ 0x снова усложняет задачу.

As

stack.pop(item); // move top data to item without copying

позволяет эффективно перемещать верхний элемент из стека. В то время как

item = stack.top(); // make a copy of the top element
stack.pop(); // delete top element

не допускает такой оптимизации.

1
ответ дан 4 December 2019 в 07:14
поделиться

Проблема подхода Java заключается в том, что его метод pop () имеет как минимум два эффекта: удаление элемента и возврат элемент. Это нарушает принцип единственной ответственности при разработке программного обеспечения, что, в свою очередь, открывает двери для сложностей проектирования и других проблем. Это также влечет за собой снижение производительности.

С точки зрения STL идея состоит в том, что иногда, когда вы pop () , вас не интересует всплывающий элемент. Вам просто нужен эффект удаления верхнего элемента. Если функция возвращает элемент, а вы его игнорируете, то это потраченная впустую копия.

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

STL не перегружает функции pop () , а скорее разделяет их на две функции: back () (или top () в случай адаптера std :: stack ) и pop () . Функция back () просто возвращает элемент, а функция pop () просто удаляет его.

4
ответ дан 4 December 2019 в 07:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: