Когда использовать boost :: необязательный и когда использовать std :: unique_ptr в тех случаях, когда вы хотите реализовать функцию, которая может возвращать & quot; ничто & quot ;?

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

* — мы игнорируем необработанную версию ptr, пару с флагом bool и исключение, когда ни одна версия не найдена.

boost::optional<Person> findPersonInList();

или же

std::unique_ptr<Person> findPersonInList();

Так есть ли причины отдавать предпочтение одному другому?

19

Решение

Это зависит от того, хотите ли вы вернуть справиться или копия.

Если вы хотите вернуть справиться:

  • Person*
  • boost::optional<Person&>

оба приемлемых варианта. Я склонен использовать Ptr<Person> класс, который выбрасывает в случае нулевого доступа, но это моя паранойя.

Если вы хотите вернуть копия:

  • boost::optional<Person> для неполиморфных классов
  • std::unique_ptr<Person> для полиморфных классов

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

25

Другие решения

Общий ответ таков: ваши намерения выражаются boost::optional и не std::unique_ptr, Тем не менее, ваш особый случай find операция, вероятно, должна соответствовать стандартному способу работы библиотеки, предполагая, что ваш базовый тип имеет концепцию итераторов: вернуть итератор в end() если элемент не найден, и итератор для элемента в противном случае.

14

boost::optional более четко заявляет ваше намерение. Вам нужно явно документировать, что пусто std::unique_ptr означает, что нет смысла возвращать

8

Существует четвертый способ сделать это: заставить функцию выдать исключение, если ничего не найдено.

Я знаю, что это на самом деле не отвечает на ваш вопрос, и поэтому я прошу прощения, но, возможно, вы не думали об этом.

6

Ах, Ксео еще не появился?

Ну, я сказал вам это однажды, и я скажу это снова: эти два совершенно разных объекта с разными целями.

  • unique_ptr средства У меня есть объект. Это просто другой способ сказать: «Я объект». Таким образом, ноль unique_ptr это то, что может привлечь внимание. Я ожидал предмета, но ничего не получил; код должен быть неправильным!
  • optional средства Иногда я могу быть не инициализирован, но это нормально. В этом случае нет никаких забот; если это Noneэто поведение, о котором думали.

Тот факт, что оба неявно преобразуются в bool, не означает, что их можно использовать с перезарядкой. использование optional с кодом, который, вероятно, не произведет никакого вывода (например, чтение потока). использование unique_ptr на заводских объектах; они будут более вероятный создайте объект для вас, а если нет, бросьте исключение.

Вывод относительно вашего примера: find должен вернуться optional,

5

Концептуально сводится к этому, учитывая необнуляемое требование:

std::optional имеет семантику значений, стековое хранилище.

std::unique_ptr есть ход семантика, куча магазина.

Если вы хотите использовать семантику значений и хранилище кучи, используйте std::indirect http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0201r1.pdf .

(Если вы хотите переместить семантику и хранилище стека … Я не знаю. Я думаю, что это unique_ptr с распределителем стека?)

2

Так есть ли причины отдавать предпочтение одному другому?

Они выражают совершенно разные намерения: optional говорит, что функция может не дать результат, чтобы дать вам (и это не случай ошибки). unique_ptr говорит вам кое-что о семантике владения (и более приемлемо для использования с нулем, чтобы выразить ошибку).

Обычно я использовал бы тот, который лучше всего выражает намерение интерфейса.

Например, предположим, что вы пишете HTTP-сервер, который пытается проанализировать полученный буфер в объект HTTP-запроса. Когда вы пытаетесь проанализировать неполный буфер, ошибки не возникает, вам просто нужно подождать и буферизовать больше данных, а затем повторить попытку.

Я бы выразил это с помощью optional, чтобы было ясно, что функция может ничего не возвращать (и ничего не возвращать — это не ошибка).

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

1