std::optional
개요
std::optional
은 C++17부터 도입된 기능으로, 값이 있을 수도 있고 없을 수도 있는 상황을 명시적으로 표현하는 데 사용되는 템플릿 클래스입니다. 함수가 유효한 값을 반환하지 못하는 경우, 이전에는 nullptr
나 특별한 값(예: -1)을 반환하여 실패를 알렸습니다. std::optional
은 이러한 상황을 더 안전하고 명확하게 처리할 수 있는 방법을 제공합니다.
C++ 버전별 주요 키워드 도입 시기
- C++17:
std::optional
도입
내용 설명
std::optional<T>
객체는 타입 T
의 값을 포함하거나, 아무 값도 포함하지 않는 두 가지 상태를 가질 수 있습니다. 값이 없는 상태는 std::nullopt
를 사용하여 표현합니다.
주요 멤버 함수는 다음과 같습니다.
has_value()
:optional
객체가 값을 가지고 있는지 확인합니다. (bool 반환)value()
: 저장된 값을 반환합니다. 값이 없는 경우std::bad_optional_access
예외를 발생시킵니다.value_or(default_value)
: 저장된 값을 반환합니다. 값이 없는 경우default_value
를 반환합니다.operator*
,operator->
: 저장된 값에 직접 접근합니다. 값이 없는 상태에서 호출하면 정의되지 않은 동작(undefined behavior)을 유발하므로,has_value()
로 확인 후 사용해야 합니다.
예제 코드
#include <iostream>
#include <optional>
#include <string>
// C++17 이상에서 컴파일해야 합니다.
using namespace std::string_literals;
// 플래그에 따라 문자열을 반환하거나, 아무것도 반환하지 않는 함수
std::optional<std::string> check(const bool flag)
{
if (flag)
return "true"s; // 값을 포함하는 optional 반환
return {}; // std::nullopt와 동일. 비어있는 optional 반환
}
int main()
{
// 1. 값 초기화 및 접근
auto v1 = std::optional<int>{42};
if (v1.has_value()) // if (v1) 와 동일
{
std::cout << *v1 << '\n'; // 포인터처럼 접근
}
// 2. value() 와 value_or()
auto v2 = std::optional<std::string>{"text"s};
std::cout << v2.value() << '\n'; // 예외 위험 있지만, 값 존재 시 안전
auto v3 = std::optional<std::string>{}; // 비어있음
std::cout << v3.value_or("default"s) << '\n'; // 비어있을 때 기본값 사용
// 3. has_value()로 상태 확인
std::cout << std::boolalpha << v2.has_value() << '\n';
std::cout << std::boolalpha << v3.has_value() << '\n';
// 4. 함수 반환값으로 활용
auto res1 = check(true);
std::cout << "check(true): " << res1.value_or("empty") << '\n';
auto res2 = check(false);
std::cout << "check(false): " << res2.value_or("empty") << '\n';
return 0;
}
실행 결과
42
text
default
true
false
check(true): true
check(false): empty
활용팁
- 함수 반환 값: 값을 반환할 수도, 그렇지 않을 수도 있는 함수의 반환 타입으로
std::optional
을 사용하면 API의 의도가 명확해집니다. - 안전한 값 접근:
value()
는 값이 없을 때 예외를 던져주므로 프로그램의 비정상적인 상태를 조기에 발견하는 데 도움이 됩니다. 반면,value_or()
는 값이 없을 때의 기본 흐름을 안전하게 처리할 때 유용합니다. - 성능: 값이 존재함이 확실한 상황에서는
*
또는->
연산자를 사용하면value()
의 예외 처리 오버헤드를 피할 수 있어 약간의 성능 이점을 얻을 수 있습니다.
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : Type Traits 2 (11, 14, 17, 20) (0) | 2025.09.27 |
---|---|
Modern C++ : Variadic Templates and Fold Expressions (11, 17) (0) | 2025.09.26 |
Modern C++ : std::concepts (20) (0) | 2025.09.25 |
Modern C++ : Type Traits 1 (11, 14, 17, 20) (0) | 2025.09.24 |
Modern C++ : 템플릿 특수화 (Template Specialization) (98, 11, 17) (0) | 2025.09.23 |
Modern C++ : 복사 및 이동 의미론 (Copy and Move Semantics) (98, 11) (0) | 2025.09.22 |
Modern C++ : 연산자 오버로딩 (Operator Overloading) (98, 11, 20) (0) | 2025.09.21 |
Modern C++ : 클래스 템플릿(Class Template) (98) (0) | 2025.09.20 |