On this page
article
std::optional
개념
std::optional
은 C++17 표준 라이브러리에서 도입된 컨테이너로, 값이 있을 수도 있고 없을 수도 있는 값을 표현하는 타입이다.
널 포인터 대신 명시적으로 값의 유무를 표현할 수 있는 타입 안전한 대안으로 사용된다.
예를 들어 함수가 값을 반환할 수도, 반환하지 않을 수도 있는 경우 std::optional
을 사용하여 반환값을 캡슐화할 수 있다.
기본 사용법
#include <optional>
#include <iostream>
std::optional<int> divide(int numerator, int denominator) {
if (denominator == 0)
return std::nullopt;
return numerator / denominator;
}
int main() {
auto result = divide(10, 2);
if (result)
std::cout << "결과: " << *result << std::endl;
else
std::cout << "0으로 나눌 수 없습니다." << std::endl;
}
std::nullopt
는 optional 객체가 값을 가지고 있지 않음을 나타내는 상수이다.
*result
는 optional 객체 내부의 값을 역참조하여 가져온다.
주요 멤버 함수
operator bool()
: 값이 있으면 true, 없으면 false 반환value()
: 값이 없으면 예외를 던지고, 있으면 값을 반환value_or(default_value)
: 값이 있으면 값을 반환하고, 없으면 기본값 반환emplace(args...)
: 내부 값을 생성자 인자를 이용해 직접 생성reset()
: optional 객체를 비어 있는 상태로 리셋
생성자 예시
#include <optional>
#include <string>
#include <iostream>
int main() {
std::optional<std::string> opt1("hello");
std::optional<std::string> opt2(std::in_place, 5, 'x');
std::cout << *opt1 << std::endl; // hello
std::cout << *opt2 << std::endl; // xxxxx
}
첫 번째 생성자는 문자열 리터럴로 초기화하고, 두 번째 생성자는 std::in_place
를 사용해 std::string(5, 'x')
생성자를 직접 호출하여 초기화한다.
값 접근 방식
값에 접근할 땐 여러 방법이 있다.
std::optional<int> opt = 10;
// 방법 1: operator*
int value1 = *opt;
// 방법 2: value()
int value2 = opt.value();
// 방법 3: value_or
int value3 = opt.value_or(0);
값이 없는데 *opt
나 opt.value()
를 호출하면 **예외(std::bad_optional_access
)**가 발생하므로 주의해야 한다.
nullopt
std::nullopt
는 optional 객체를 비워두기 위해 사용한다.
std::optional<int> opt1; // 비어 있음
std::optional<int> opt2 = std::nullopt; // 비어 있음
opt1 = 5; // 값 할당
opt2 = opt1; // 값 복사
opt1.reset(); // 값 제거
std::nullopt
는 std::optional
타입과 함께 쓰이며, 값 없음 상태를 표현한다.
참조 optional
C++20부터 std::optional
은 참조 타입(std::optional<int&>
)도 지원한다.
int x = 10;
std::optional<int&> ref = x;
if (ref)
*ref = 20;
std::cout << x << std::endl; // 20
참조 optional은 객체의 참조를 캡슐화하여 값이 있을 수도, 없을 수도 있는 참조를 다룰 수 있다.