0

0

c++ std::variant怎么用 c++类型安全的union【详解】

穿越時空

穿越時空

发布时间:2025-12-26 15:46:02

|

944人浏览过

|

来源于php中文网

原创

std::variant是C++17引入的类型安全联合体,可存储多种类型之一并运行时明确当前类型;它通过内部索引和类型标签确保访问安全,支持std::get、std::holds_alternative和std::visit等操作。

c++ std::variant怎么用 c++类型安全的union【详解】

std::variant 是 C++17 引入的类型安全联合体(type-safe union),它能在一个对象中存储多种不同类型中的某一种,同时在运行时明确知道当前存的是哪一种——彻底避免了传统 union 的类型擦除和未定义行为风险。

核心特点:比 union 更安全、比 void* 更清晰

传统 union 不记录当前活跃成员,读写错误类型会触发未定义行为;std::variant 内部自带“当前索引”(index)和类型标签,所有访问都受检查:

  • 构造时自动记录所选类型
  • std::get<T>(v)std::get<i>(v) 访问前会做运行时校验(debug 模式下抛 std::bad_variant_access
  • 支持 std::holds_alternative<T>(v) 判断是否持有某类型
  • 支持 std::visit 对不同情况统一处理,无需手动 switch index

基本用法:声明、构造、访问

假设你想表示一个可能为整数、浮点数或字符串的值:

#include <variant>
#include <string>
#include <iostream>
<p>using MyVariant = std::variant<int, double, std::string>;</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/6e7abc4abb9f" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">C++免费学习笔记(深入)</a>”;</p><div class="aritcle_card flexRow">
                                                        <div class="artcardd flexRow">
                                                                <a class="aritcle_card_img" href="/ai/859" title="Tome"><img
                                                                                src="https://img.php.cn/upload/ai_manual/000/000/000/175679992061586.jpg" alt="Tome"  onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
                                                                <div class="aritcle_card_info flexColumn">
                                                                        <a href="/ai/859" title="Tome">Tome</a>
                                                                        <p>先进的AI智能PPT制作工具</p>
                                                                </div>
                                                                <a href="/ai/859" title="Tome" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
                                                        </div>
                                                </div><p>MyVariant v1 = 42;                // 自动推导为 int
MyVariant v2 = 3.14;              // 推导为 double
MyVariant v3 = std::string{"hi"}; // 必须显式构造 string,否则会被当 const char*

访问方式有三种常用形式:

  • std::get<int>(v1) —— 按类型取,失败抛异常
  • std::get<0>(v1) —— 按序号取(0=first type=int),同样带检查
  • std::holds_alternative<double>(v1) —— 先判断再取,避免异常

推荐写法:用 std::visit 处理多态逻辑

比起一堆 if (holds_alternative<...>)std::visit 更简洁、更不易漏分支:

std::visit([](const auto& x) {
    using T = std::decay_t<decltype(x)>;
    if constexpr (std::is_same_v<T, int>) {
        std::cout << "int: " << x << '\n';
    } else if constexpr (std::is_same_v<T, double>) {
        std::cout << "double: " << x << '\n';
    } else if constexpr (std::is_same_v<T, std::string>) {
        std::cout << "string: " << x << '\n';
    }
}, v1);

也可以用重载的 lambda(C++17 起支持):

auto printer = [](const auto& x) {
    std::cout << x << '\n';
};
std::visit(printer, v1); // 自动匹配对应类型的 operator()

实用细节与注意事项

  • std::monostate 可作为占位类型,让 variant 支持“空状态”,比如 std::variant<std::monostate, int, std::string>
  • variant 不允许包含自身类型(如 std::variant<int, std::variant<...>>),但可通过 std::unique_ptr 间接实现递归结构
  • 移动语义完整支持:move 构造/赋值后原对象处于有效但未指定状态(通常为第一个类型的默认值)
  • 大小是各备选类型最大 size + 少量控制字节(一般 1–2 字节),比 std::any 更轻量

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1030

2023.08.02

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

847

2023.08.22

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

569

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

441

2024.03.13

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

27

2025.11.27

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.4万人学习

SQL 教程
SQL 教程

共61课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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