web-dev-qa-db-ja.com

オプションをreference_wrapperと組み合わせるのは理にかなっていますか?

C++では、タイプstd::optional<std::reference_wrapper<T>>を使用できることに気づきました。このタイプのオブジェクトは、基本的に、タイプTのオブジェクトへの参照、またはnull値、つまりほとんどポインターです。私の質問:

  1. std::optional<std::reference_wrapper<T>>T*の間に概念的な違いはありますか?

  2. 実用的な違いはありますか? std::optional<std::reference_wrapper<T>>よりもT*を選択することをお勧めする状況はありますか?

19
Bobby

_std::optional<std::reference_wrapper<T>>_と_T*_の間に概念的な違いはありますか?

_std::optional<>_は、その名前がす​​でに示唆しているように、値を持つことができる場合、またはまったく値を持たない可能性がある場合に使用することを目的としています。

_T*_オブジェクトに値がないに相当するものは、それにnullptrを割り当てることです。つまり、ポインタはnowheresomewhere(またはanywhere、つまり:初期化されていない)とは対照的。 _std::optional<>_は、任意の型へのポインタのnullptrの概念をエクスポートしていると言えます。したがって、それらは概念的に非常に類似しており、_std::option<>_アプローチは一種の一般化であると言えます。

実用的な違いはありますか? _std::optional<std::reference_wrapper<T>>_よりも_T*_を選択することが推奨される状況はありますか?

サイズが思い浮かびます。 _std::optional<>_には、値の有無を示す内部フラグが含まれていますが、_T*_の場合、nullptrはポインターが格納できる値の1つとして直接エンコードされます。したがって、_std::optional<std::reference_wrapper<T>>_オブジェクトは_T*_よりも大きくなります。

安全性に関しては、_T*_とは異なり、_std::optional<>_はメンバー関数value()を提供し、値がない場合は例外をスローします(安全でないoperator*() _T*_と同じように)。

また、たとえば、関数の戻り値として_std::optional<std::reference_wrapper<T>>_の代わりに_T*_を使用すると、より明示的な方法で値がない可能性があることを示す場合があります。すべて。

5
眠りネロク

std::optional<std::reference_wrapper<T>>T*の主な違いは、T*では、ポイントされたメモリの所有者について考える必要があることです。

関数がT*を返す場合は、メモリを解放する責任があるのか​​、他の誰かが責任を負うのかを知る必要があります。それが参照であるとき、それはあなたが心配しなければならないことではありません。

1
TimK