optional
std::optional 是 C++17 引入的模板类,表示"可能有值,也可能为空"的语义。它是函数返回"可能失败"结果时最干净的表述方式,替代了用哨兵值(如 -1、nullptr)或返回 pair<bool, T> 的做法。
头文件与基本特征
#include <optional>
| 特征 | 说明 |
|---|---|
| 作用 | 安全表示"可能有值"的语义 |
| 为空时 | has_value() 返回 false |
| 访问值 | value() 或 * / ->,为空时 value() 抛异常 |
| 默认值 | value_or(default) 为空时返回默认值 |
| 不是指针 | 值语义,可拷贝、移动,无动态内存分配 |
基本用法
#include <iostream>
#include <optional>
#include <string>
std::optional<int> parse(const std::string& s) {
if (s.empty()) {
return std::nullopt; // 空 optional
}
return std::stoi(s); // 有值
}
int main() {
std::optional<int> r1 = parse("42");
std::optional<int> r2 = parse("");
if (r1.has_value()) {
std::cout << "r1 = " << r1.value() << '\n'; // 42
}
std::cout << "r2 default = " << r2.value_or(-1) << '\n'; // -1
return 0;
}
常用接口
| 接口 | 作用 |
|---|---|
has_value() | 是否有值 |
value() | 获取值,为空抛 std::bad_optional_access |
operator* / operator-> | 访问内部值(不检查) |
value_or(default) | 有值则返回,否则返回默认值 |
reset() | 清空 |
emplace(args...) | 原地构造 |
std::nullopt | 表示空 optional |
典型场景
- 函数返回"可能找不到"的结果(替代
pair<bool, T>或指针)。 - 配置项中的可选字段。
- 缓存的"已计算/未计算"状态。
std::optional<std::string> findUser(int id) {
if (id <= 0) return std::nullopt;
return "user_" + std::to_string(id);
}
使用注意
*和->在空时不抛异常,是未定义行为——优先has_value()或value()。optional的值本身存储在栈上(或容器内),不需要堆分配。- 不要用
optional<T&>(C++17 不支持引用 optional)。
小结
std::optional 让"可能为空"成为类型系统的一部分。用它替代哨兵值和输出参数后,接口意图更明确,调用侧的逻辑也更清晰。