首页 > 后端开发 > C++ > 正文

C++17对STL带来哪些新特性 介绍optional variant any用法

P粉602998670
发布: 2025-07-25 10:14:02
原创
309人浏览过

c++++17通过引入optional、variant和any增强了stl,使代码更安全、灵活且简洁。1. std::optional用于优雅处理可能缺失的值,避免空指针或无效值错误;2. std::variant提供类型安全的联合体,支持编译时类型检查,替代不安全的union;3. std::any允许运行时存储任意类型,但需自行确保类型安全,使用时应谨慎以避免“类型地狱”。三者各有适用场景:optional适合表示可选值,variant适合多类型安全切换,any适合真正需要动态类型的场合。在项目中应逐步引入这些特性,优先考虑类型安全与性能平衡。

C++17对STL带来哪些新特性 介绍optional variant any用法

C++17对STL的增强,核心在于让代码更安全、更灵活,也更简洁。optional解决的是空值问题,variant提供了类型安全的联合体,而any则允许你在运行时存储任何类型的值。它们都旨在减少错误,提高代码的可读性和可维护性。

C++17对STL带来哪些新特性 介绍optional variant any用法

std::optional:优雅地处理可能缺失的值

以前,我们经常用指针或者特定的“无效值”来表示一个值可能不存在。但这容易出错,比如空指针解引用或者忘记检查无效值。std::optional提供了一种更清晰、更安全的方式。

C++17对STL带来哪些新特性 介绍optional variant any用法

假设你需要一个函数来查找用户ID对应的名字,但用户可能不存在。

立即学习C++免费学习笔记(深入)”;

#include <iostream>
#include <optional>
#include <string>
#include <map>

std::optional<std::string> find_name(int user_id) {
  static std::map<int, std::string> users = {
    {123, "Alice"},
    {456, "Bob"}
  };

  if (users.count(user_id)) {
    return users[user_id];
  } else {
    return std::nullopt;
  }
}

int main() {
  auto name = find_name(123);
  if (name) {
    std::cout << "Name: " << *name << std::endl;
  } else {
    std::cout << "User not found" << std::endl;
  }

  name = find_name(789);
  if (name.has_value()) { // 或者 if (name)
    std::cout << "Name: " << *name << std::endl;
  } else {
    std::cout << "User not found" << std::endl;
  }

  return 0;
}
登录后复制

这段代码比使用裸指针或者特殊字符串来表示“未找到”要清晰得多。optional强制你显式地处理值可能不存在的情况。

C++17对STL带来哪些新特性 介绍optional variant any用法

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

C语言的union类型虽然灵活,但类型不安全。std::variant解决了这个问题。它可以存储多个类型中的一个,但只能同时存储一个,并且在编译时进行类型检查。

比如,你需要一个可以存储整数、浮点数或者字符串的变量:

无阶未来模型擂台/AI 应用平台
无阶未来模型擂台/AI 应用平台

无阶未来模型擂台/AI 应用平台,一站式模型+应用平台

无阶未来模型擂台/AI 应用平台 35
查看详情 无阶未来模型擂台/AI 应用平台
#include <iostream>
#include <variant>
#include <string>

int main() {
  std::variant<int, float, std::string> data;

  data = 10;
  std::cout << "Data (int): " << std::get<int>(data) << std::endl;

  data = 3.14f;
  std::cout << "Data (float): " << std::get<float>(data) << std::endl;

  data = "Hello";
  std::cout << "Data (string): " << std::get<std::string>(data) << std::endl;

  // 错误示例:尝试获取错误类型的variant值
  // std::cout << std::get<int>(data) << std::endl; // 会抛出std::bad_variant_access

  // 使用std::visit进行更灵活的处理
  std::visit([](auto& arg){
    using T = std::decay_t<decltype(arg)>;
    if constexpr (std::is_same_v<T, int>){
      std::cout << "int: " << arg << '\n';
    } else if constexpr (std::is_same_v<T, float>){
      std::cout << "float: " << arg << '\n';
    } else if constexpr (std::is_same_v<T, std::string>){
      std::cout << "string: " << arg << '\n';
    }
  }, data);

  return 0;
}
登录后复制

std::get用于访问variant中存储的值。如果尝试访问错误的类型,会抛出异常。std::visit提供了一种更安全、更灵活的方式来处理variant,它允许你定义一个函数对象来处理不同的类型。

std::any:存储任何类型的值,但要小心

std::any可以存储任何类型的值,这听起来很强大,但也意味着你需要自己负责类型安全。

#include <iostream>
#include <any>
#include <string>

int main() {
  std::any data;

  data = 10;
  std::cout << "Data (int): " << std::any_cast<int>(data) << std::endl;

  data = "Hello";
  std::cout << "Data (string): " << std::any_cast<std::string>(data) << std::endl;

  // 错误示例:尝试转换成错误的类型
  try {
    std::cout << std::any_cast<float>(data) << std::endl;
  } catch (const std::bad_any_cast& e) {
    std::cerr << "Error: " << e.what() << std::endl;
  }

  // 使用 has_value() 和 type() 进行类型检查
  if (data.has_value()) {
    std::cout << "Data type: " << data.type().name() << std::endl;
  }

  return 0;
}
登录后复制

std::any_cast用于从any对象中提取值。如果类型不匹配,会抛出std::bad_any_cast异常。 any的优点是灵活性,缺点是类型安全不如variant

optionalvariantany 的选择:权衡利弊

选择哪个特性取决于你的具体需求。

  • 如果你需要表示一个值可能不存在,optional是最佳选择。
  • 如果你需要存储多个类型中的一个,并且需要在编译时进行类型检查,variant是更好的选择。
  • 如果你需要在运行时存储任何类型的值,并且愿意自己负责类型安全,any是唯一的选择。

如何在现有项目中使用这些新特性?

逐步引入。先从小的、独立的模块开始,逐渐替换旧的代码。不要试图一次性重写整个项目。使用这些新特性时,要充分考虑类型安全和性能。

variant的性能考量:真的比union慢吗?

理论上,variant会比union慢一些,因为它需要维护当前存储的类型信息。但在实际应用中,这种差异通常可以忽略不计。而且,variant的类型安全带来的好处远大于这点性能损失。编译器优化也可能减少这种差异。

any的滥用:如何避免成为“类型地狱”的受害者?

any很强大,但也容易被滥用。过度使用any会导致代码难以理解和维护,最终变成“类型地狱”。只在真正需要存储任意类型的值时才使用any,并且要尽可能地进行类型检查。

以上就是C++17对STL带来哪些新特性 介绍optional variant any用法的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号