【C++学習|豆知識】C++17のstd::optionalで「値がない状態」をスマートに扱う方法

1. 導入

C++でプログラミングをしていると、「値が存在しない」状態をどのように表現すべきか悩むことはありませんか?以前は、ポインタを渡してnullptrで判定したり、-1のような「ありえない値」を代入したりして凌いでいたかもしれません。しかし、これらはバグの温床になりがちです。C++17で導入された std::optional は、まさにこの「値があるか、空か」という状態を型として安全に表現するために不可欠なツールです。

2. 基礎知識

std::optional は、型Tの値を保持するか、あるいは「何も保持していない(空)」状態を保持するコンテナのようなクラスです。
これまで「戻り値がないこと」を表現するために、わざわざ動的メモリ確保をしてポインタを返していた場面でも、std::optionalを使うことで、メモリ管理のオーバーヘッドを抑えつつ、直感的なコードを書くことができます。

3. 実装/解決策

std::optionalを使用するには、ヘッダファイル をインクルードします。値を取得する際は、値が存在するかどうかを has_value() メソッドで確認するか、単純に if (optional変数) と記述することで判定可能です。値を取り出すには value() メソッドや、ポインタのように振る舞う operator を使用します。

4. サンプルプログラム

以下のコードは、数値が偶数かどうかを判定し、偶数の場合のみ値を返す関数の例です。

#include
include

// 偶数なら値を返し、奇数なら「空」を返す関数
std::optional get_even_number(int value) {
if (value % 2 == 0) {
return value; // 値をセットして返す
}
return std::nullopt; // 値がないことを明示的に示す
}

int main() {
int test_values[] = {10, 7};

for (int val : test_values) {
auto result = get_even_number(val);

// 値が存在するかどうかを確認
if (result.has_value()) {
std::cout << val << " は偶数です: " << result.value() << std::endl; } else { // 値がない場合の処理 std::cout << val << " は奇数(または値なし)です。" << std::endl; } } return 0; }

5. 応用・注意点

現場で使う際に注意すべき点は、値が空の状態で value() を呼び出すと std::bad_optional_access 例外が発生するという点です。必ず事前に判定を行うか、value_or() を活用しましょう。
例えば、result.value_or(0) と書けば、「値があればその値を、なければ0を返す」という簡潔な記述が可能です。また、std::optionalはスタック上に値を保持するため、巨大な構造体などを格納する場合は、移動セマンティクスを意識してパフォーマンスを最適化するようにしてください。

コメント

タイトルとURLをコピーしました