C++で値がないかもしれない戻り値にstd::optionalを使う
C++で「値がないかもしれない」を表したいとき、std::optional が使えます。
たとえば検索して見つからなかった場合や、文字列を数値に変換できなかった場合です。
optionalを返す
#include <optional>
#include <string>
#include <vector>
std::optional<std::string> findName(int id) {
if (id == 1) {
return "alice";
}
return std::nullopt;
}
値がある場合はそのまま返し、ない場合は std::nullopt を返します。
呼び出し側は、値があるかを確認します。
auto name = findName(1);
if (name) {
// *name で値を取り出す
}
value_orを使う
デフォルト値があるなら value_or() が使えます。
std::string name = findName(2).value_or("unknown");
見つからなかった場合は "unknown" になります。
例外とoptionalの違い
std::optional は、失敗が普通に起こる場合に向いています。
- IDで検索して見つからない
- 設定値が省略されている
- 入力が空だった
こういうケースは、例外というより「値がない」として扱う方が読みやすいです。
一方で、ファイルが壊れている、前提条件が崩れている、復帰できない失敗なら例外の方が合う場合もあります。
ポインタとの違い
参照先がないことを表すだけならポインタでも書けます。
const User* findUser(int id);
ただ、戻り値として値そのものを返したい場合は std::optional<User> の方が意図が伝わります。
std::optional<User> findUser(int id);
所有権を返したい場合はスマートポインタを使います。所有権の話は C++でunique_ptrとshared_ptrを使い分ける目安 に分けています。
まとめ
std::optional は「値がないかもしれない」を型で表します。
- 見つからない可能性がある戻り値に使う
- 値なしは
std::nullopt - デフォルト値には
value_or() - 失敗が普通に起こるなら例外より読みやすいことがある
- 所有権を返すならスマートポインタも候補
戻り値の意味を型に出したいときに、std::optional はかなり使いやすいです。


