77.单一变量存放多种类型的数据
今天的主题是:如何在一个变量中存储多种类型的数据
(这是一个C++17的特性)
如何做到呢?要用到一个叫**std::variant
**的东西(variant意思:变种,变形,各种各样的,易变的)
🍅概述variant
它和option
很像,它的作用是让我们不用担心处理确切的数据类型,只有一个变量,之后我们在考虑它的具体类型
故我们做的就是指定一个叫std::variant
的东西,然后列出它可能的数据类型
std::variant
允许你列出所有可能的类型,然后你可能决定它将是什么
🍅具体使用
首先要包含头文件#include <variant>
#include <iostream>
#include <variant>
int main() {
//列举出可能的类型
std::variant<std::string, int> data;
data = "Cherno";
//访问variant的数据是利用std::get< >( )
std::cout << std::get<std::string>(data) << "\n";
data = 2;
std::cout << std::get<int>(data) << "\n";
return 0;
}
那么如何知道当前的variant中存的是什么东西呢?
利用.index()
函数便可
//string的索引是0,int的索引是1
std::variant<std::string, int> data;
data = "Cherno";
std::cout << data.index() << "\n"; //这里会输出0
data = 1;
std::cout << data.index() << "\n"; //这里会输出1
当然,还有更好的方法
便是利用get_if
函数
//string的索引是0,int的索引是1
std::variant<std::string, int> data;
data = "Cherno";
//get_if需要接收variant的地址,然后会返回一个指针
//如下面例子,如果data是字符串,则返回一个指向该字符串的指针
//如果不是字符串,则返回一个空指针
auto valuePoint = std::get_if<std::string>(&data);
如果结合一下if,则会更加好用
std::variant<std::string, int> data;
data = "Cherno";
//如果data的值是字符串,则进一步对其进行操作
if (auto valuePoint = std::get_if<std::string>(&data)) {
std::string &str = *valuePoint;
}
get_if
的方法是最推荐的。因为它干净且有用,可读性也高(index返回个01234还得回去猜猜各个索引代表的是什么)
那么variant
和union
有何不同呢
//如果是union
union {
double a, int b;
}
则这个union的大小就是最大的类型的大小,即为8个字节
而如果是variant
std::variant<int, double> data;
得到的大小将会是int + double
的大小,即是12字节
故此二者的区别就有了
- union相当于将里面的变量都同一丢在一个内存块里(当然是以最大的类型为标准)
- 而variant是为你创建了一个结构体或者类,它只是将这多种的类型数据储存为那个类或结构体中的成员,只是看起来更加简洁罢了
所以从技术上讲,union仍然是更有效率和更好的
然而variant更加安全(对于类型),不会造成未定义行为,所以应当去使用它,除非做的是底层优化,非常需要性能