现代 C++ 常用工具类型

现代 C++ 常用工具类型

时间:2026/04/09

关键词:optionalvariantanystring_viewspanexpected
核心目标:掌握几个现代 C++ 里非常高频、能直接改善接口表达和代码质量的标准库类型。


1. 为什么这些类型重要

现代 C++ 的很多进步,不只在语法,还在于:

  • 用更明确的类型表达意图

比如:

  • “可能没有值”
  • “可能是多种类型之一”
  • “只读字符串视图”
  • “一段连续内存视图”

这些都不该继续靠:

  • nullptr
  • 魔法值
  • void*
  • 裸指针 + 长度

来硬撑。


2. std::optional<T>:可能有,也可能没有

1
2
3
#include <optional>

std::optional<int> find_id();

它适合表达:

  • 成功返回一个值
  • 失败时没有值

比“返回 -1 表示失败”更清晰。

常用接口:

  • has_value()
  • value()
  • value_or(default)

3. std::variant:类型安全的联合体

1
2
3
#include <variant>

std::variant<int, std::string> v;

它表示:

  • 值一定是若干候选类型中的一个

相比传统 union,它:

  • 类型安全
  • 自动管理对象生命周期

配合 std::visit 很常见。


4. std::any:完全动态类型

1
2
3
4
#include <any>

std::any x = 42;
x = std::string("hello");

它适合:

  • 真正不知道运行期会是什么类型

但代价是:

  • 类型信息晚到运行期
  • 可读性和性能都不如 variant

经验上:

  • 能用 variant 就不要先上 any

5. std::string_view:无拷贝字符串视图

1
2
3
#include <string_view>

void print(std::string_view s);

优点:

  • 不拥有字符串
  • 不分配内存
  • 可接 std::string、字面量、子串视图

风险:

  • 它不延长底层字符串生命周期

所以不能把它保存得比源字符串活得更久。


6. std::span<T>:无拷贝连续内存视图

1
2
3
#include <span>

void process(std::span<const int> xs);

适合:

  • 数组
  • std::vector
  • std::array

相比传:

  • 裸指针 + 长度

更清晰,也更安全。


7. std::expected:值或错误

如果你的环境支持 C++23,可以关注:

1
std::expected<Value, Error>

它适合表达:

  • 成功时返回值
  • 失败时返回明确错误信息

相比 optional,它多了:

  • 为什么失败

8. 这些类型最核心的接口收益

8.1 optional

不再靠魔法值表示“没有结果”。

8.2 variant

不再靠手写 tag + union。

8.3 string_view

函数参数更轻、更泛化。

8.4 span

数组接口更现代。


9. 常见坑

9.1 string_view / span 生命周期错误

它们都只是视图,不拥有数据。

9.2 用 any 代替清晰设计

很多时候 any 只是把类型问题往后拖。

9.3 optional 里塞重对象却频繁拷贝

虽然语义清晰,但也要注意值类别和性能。


10. 一页总结

这几个类型的价值可以压缩成一句话:

用更准确的标准库类型表达接口语义,减少魔法值、裸指针和不透明约定。

最值得优先掌握的顺序通常是:

  1. optional
  2. string_view
  3. span
  4. variant
  5. any
  6. expected