C++ 17 std::optional

C++ 17 std::optional

std::optional 用来表示“一个值可能存在,也可能不存在”。它很适合替代那些用特殊值、空指针或者额外布尔标记来表示“无结果”的老写法。

1. 为什么需要 std::optional?

以前一个函数如果可能取不到值,常见写法一般是:

  • 返回特殊值,比如 -1
  • 通过输出参数返回
  • 返回指针或 nullptr

这些方式都能工作,但表达力不够直接。
std::optional<int> 一眼就能看出:这个函数返回的是“可能为空的 int”。

2. 基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <optional>
#include <iostream>
using namespace std;

optional<int> findValue(bool ok)
{
if (ok) {
return 100;
}
return nullopt;
}

int main()
{
auto ret = findValue(true);
if (ret.has_value()) {
cout << ret.value() << endl;
}
return 0;
}

3. 常用接口

3.1 has_value()

判断当前是否真的有值:

1
2
if (ret.has_value()) {
}

3.2 value()

获取内部值:

1
cout << ret.value() << endl;

如果当前没有值,调用 value() 会抛异常。

3.3 value_or()

提供一个默认值:

1
cout << ret.value_or(0) << endl;

这在很多场景下都比手动 if 判断更顺手。

4. 一个更贴近业务的例子

1
2
3
4
5
6
7
8
9
10
11
#include <optional>
#include <string>
using namespace std;

optional<string> getNickName(bool hasNick)
{
if (hasNick) {
return "Tom";
}
return nullopt;
}

调用端可以非常自然地写:

1
2
auto name = getNickName(false);
cout << name.value_or("Guest") << endl;

5. 和指针返回有什么区别?

指针

  • 语义偏“对象地址”
  • 容易让人联想到生命周期和所有权问题

optional

  • 语义偏“这个值可能没有”
  • 更适合普通值类型返回

如果你表达的是“有或者没有这个结果”,而不是“对象引用关系”,通常 optional 更贴切。

6. 使用时要注意的点

6.1 不要滥用 value()

如果没有先判断就直接 value(),还是会有异常风险。
很多时候 value_or() 更顺手。

6.2 不是所有对象都适合 optional

对于特别重的大对象,频繁构造和拷贝 optional<T> 也要注意成本。

6.3 它不是错误处理机制的全部

optional 适合表示“有没有值”,但如果你还需要表达详细错误原因,那它可能就不够了。

总结

std::optionalC++17 里非常实用的库特性之一。
它把“可能没有结果”这个需求表达得很自然,能让接口比“返回特殊值”更清晰。日常开发里,查找、配置读取、解析结果这类场景都很适合用它。