C++ std::optional详解 | 可选值类型设计

C++ std::optional:优雅处理可选值 #

引言 #

前几天交流群里看到老王在聊C++的tuple,说tuple非常好用,我在群里向老王推荐使用optional,但没想到,老王居然不知道optional,所以我想,有必要输出一篇文章介绍下optional。希望更多的人都能在开发中用上optional这种高级实用的特性。

How:如何使用std::optional #

optional 是C++17引入的新特性,它是个模板类std::optional,它提供了一个可选的值,可以表示一个变量可能有值,也可能没有值。

它有几个基本用法:

  1. 初始化:可以直接初始化 std::optional 为某个值,或者不初始化(此时为 std::nullopt)。

  2. 访问:可以通过 .value() 方法获取值,或者使用 -> 操作符访问内部对象,或者使用.value_or()获取值,如果没有值,会自动返回or配置的值。

  3. 检查:使用 .has_value() 来检查 std::optional 是否包含值。

When:何时使用std::optional #

有很多场景下,我们都可以考虑使用optional,或者可以说,很多场景下,只有使用optional才是合适的:

  1. 某个函数,它某些情况下需要返回值,某些情况下不需要返回值

  2. 需要表示一个可能不存在的值

  3. 想要避免使用指针来表示可能为空的情况。

Why:为什么使用std::optional #

我整理了几个原因:

  1. 可以避免空指针异常:传统的使用指针来表示可选值的方法可能会引起空指针异常,而std::optional提供了一种类型安全的方式来处理这种情况。

  2. 代码更加清晰:可以明确的表示某个值是可选的,以前用指针表示的时候,我们不太清楚nullptr的返回究竟是正常情况还是异常情况,而有了optional,我们可以清晰的知道,这个就是可选值。

  3. 类型安全:提供了类型安全的方式来处理可能为空的值。

实际代码示例

#include <iostream>
#include <optional>

// 函数可能返回一个整数,也可能不返回
std::optional<int> get_optional(bool return_value) {
  if (return_value) {
    return 42; // 返回一个值
  } else {
    return std::nullopt; // 不返回值
  }
}

int main() {
  auto value = get_optional(true); // 有值
  if (value) {
    std::cout << "Value is: " << *value << std::endl;
  } else {
    std::cout << "No value" << std::endl;
  }

  auto no_value = get_optional(false); // 无值
  if (no_value) {
    std::cout << "Value is: " << *no_value << std::endl;
  } else {
    std::cout << "No value" << std::endl;
  }
  return 0;
}

思考题 #

std::optional是C++17引入的新特性,如果我们不用C++17,难道就没法用了吗?自己实现一个可行吗?