std::optional<T> đại diện cho giá trị có thể có hoặc không — thay thế cho nullptr, -1, hoặc out-param bool.
cpp
// Trước C++17: trả pointer (nguy hiểm) hoặc sentinel
int* findUser(int id); // nullptr nếu không tìm thấy
// C++17: rõ ràng, type-safe
std::optional<User> findUser(int id) {
if (id == 42) return User{"Alice"};
return std::nullopt; // không có giá trị
}
auto u = findUser(42);
if (u.has_value()) {
std::cout << u->name; // dùng -> như pointer
std::cout << u.value().name; // hoặc .value() — throw nếu nullopt
}
std::string name = u.value_or("Unknown"); // fallbackDùng khi: hàm có thể thất bại mà không phải lỗi (lookup, parse), optional config field.
Không dùng khi: lỗi thực sự — dùng exception; polymorphism — dùng pointer.
std::optional<T> represents a value that may or may not be present — a type-safe alternative to nullptr, -1, or a boolean out-parameter.
cpp
// Pre-C++17: return pointer (dangerous) or sentinel
int* findUser(int id); // nullptr if not found
// C++17: explicit, type-safe
std::optional<User> findUser(int id) {
if (id == 42) return User{"Alice"};
return std::nullopt; // no value
}
auto u = findUser(42);
if (u.has_value()) {
std::cout << u->name; // use -> like a pointer
std::cout << u.value().name; // or .value() — throws if nullopt
}
std::string name = u.value_or("Unknown"); // fallbackUse when: a function can legitimately fail without it being an error (lookup, parse), optional config fields.
Don't use when: real error conditions — use exceptions; polymorphism — use pointers.