Ответ 1
Существует ли какая-либо концептуальная разница между
std::optional<std::reference_wrapper<T>>
иT*
?
std::optional<>
, как уже указывает название, предназначено для использования, когда мы можем иметь значение или вообще не иметь никакого значения.
Эквивалент, не имеющий значения для объекта T*
, будет присваивать ему nullptr
, т.е. Указатель укажет на никуда, в отличие от где-нибудь (или даже где-нибудь, т.е. Неинициализированного). Можно сказать, что std::optional<>
экспортирует концепцию nullptr
для указателей на любой произвольный тип. Итак, я бы сказал, что они концептуально очень похожи, поскольку std::option<>
подходит к своего рода обобщению.
Есть ли какая-то практическая разница? Существуют ли ситуации, когда было бы целесообразно выбрать
std::optional<std::reference_wrapper<T>>
overT*
?
Я могу думать о размере. std::optional<>
содержит внутренний флаг для указания наличия/отсутствия значения, тогда как для T*
значение nullptr
кодируется непосредственно как одно из значений, которое может хранить указатель. Таким образом, объект std::optional<std::reference_wrapper<T>>
будет больше, чем T*
.
Когда дело доходит до безопасности, в отличие от T*
, std::optional<>
предоставляет value()
функции-члена value()
которое генерирует исключение, если нет значения (он предоставляет, а также небезопасный operator*()
как это делает T*
).
Кроме того, используя std::optional<std::reference_wrapper<T>>
вместо T*
, например, как возвращаемое значение функции, может указывать более явным образом, что вообще не может быть никакого значения.