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(v)std::get(v) 访问前会做运行时校验(debug 模式下抛 std::bad_variant_access
  • 支持 std::holds_alternative(v) 判断是否持有某类型
  • 支持 std::visit 对不同情况统一处理,无需手动 switch index

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

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

#include 
#include 
#include 

using MyVariant = std::variant;

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

爱图表
爱图表

AI驱动的智能化图表创作平台

下载

MyVariant v1 = 42; // 自动推导为 int MyVariant v2 = 3.14; // 推导为 double MyVariant v3 = std::string{"hi"}; // 必须显式构造 string,否则会被当 const char*

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

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

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

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

std::visit([](const auto& x) {
    using T = std::decay_t;
    if constexpr (std::is_same_v) {
        std::cout << "int: " << x << '\n';
    } else if constexpr (std::is_same_v) {
        std::cout << "double: " << x << '\n';
    } else if constexpr (std::is_same_v) {
        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<:monostate int std::string>
  • variant 不允许包含自身类型(如 std::variant>),但可通过 std::unique_ptr 间接实现递归结构
  • 移动语义完整支持:move 构造/赋值后原对象处于有效但未指定状态(通常为第一个类型的默认值)
  • 大小是各备选类型最大 size + 少量控制字节(一般 1–2 字节),比 std::any 更轻量

相关专题

更多
string转int
string转int

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

311

2023.08.02

if什么意思
if什么意思

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

703

2023.08.22

switch语句用法
switch语句用法

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

514

2023.09.21

Java switch的用法
Java switch的用法

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

401

2024.03.13

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

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

14

2025.11.27

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

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

246

2023.08.03

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

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

203

2023.09.04

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

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

1428

2023.10.24

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

25

2025.12.25

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 4万人学习

Sass 教程
Sass 教程

共14课时 | 0.7万人学习

Pandas 教程
Pandas 教程

共15课时 | 0.8万人学习

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

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