C++ 为什么我';我用std::variant访问std::bad\u variant\u?

C++ 为什么我';我用std::variant访问std::bad\u variant\u?,c++,c++17,ubuntu-18.04,variant,gcc7,C++,C++17,Ubuntu 18.04,Variant,Gcc7,考虑: #include <variant> #include <iostream> int main() { double foo = 666.666; std::variant<double, uint64_t> v = foo; std::cout << std::get<uint64_t>(v) << std::endl; return 0; } 为什么? 我知道std::vari

考虑:

#include <variant>
#include <iostream>

int main()
{
    double foo = 666.666;
    std::variant<double, uint64_t> v = foo;
    std::cout << std::get<uint64_t>(v) << std::endl;
    return 0;
}
为什么?


我知道
std::variant
将取代
union
。但是,如果这种基本的东西失败了,它有什么好处呢

我知道std::variant将取代union

对。有点但是你的误解似乎是C++中的工会。发件人:

从工会成员处读取不是最近编写的内容是未定义的行为。许多编译器作为非标准语言扩展实现了读取联盟中非活动成员的能力

注意,这与C不同,这是一个常见误解的一个根本原因,即访问C++中的非活动成员也将被允许。 为什么?

因为
std::variant
模拟了联合,但增加了一些安全性,而且

基于索引的值访问器:如果v.Index()==I,则返回对存储在v中的值的引用否则,抛出std::bad\u variant\u访问。如果I不是变量中的有效索引,则调用的格式错误


但是,如果这种基本的东西失败了,它有什么好处呢

<> C++中的联盟从来没有被使用过。当您希望将两个或多个值压缩到同一内存中时(但在任何时候仅使用其中一个值),联合是为了节省内存。我从未遇到过它们的真正用例<代码> STD::变体不过,C++的添加很好。更大的情况是,很久以来就已经有了所谓的产品类型,比如
std::pair
,从这个意义上讲,它们可以表示的一组值是
T1 x T2
。使用<代码> STD::(和<代码> STD::任何< /代码>)现在C++也有适当的(=具有一个类型的类型安全性,您从未从联盟中得到)和类型,即值A组代码> STD::变体< /代码>可以表示是<代码> T1+T2< /Calp>(抱歉使用草率符号,希望它是清楚的)。p> 我知道std::variant将取代union

对。有点但是你的误解似乎是C++中的工会。发件人:

从工会成员处读取不是最近编写的内容是未定义的行为。许多编译器作为非标准语言扩展实现了读取联盟中非活动成员的能力

注意,这与C不同,这是一个常见误解的一个根本原因,即访问C++中的非活动成员也将被允许。 为什么?

因为
std::variant
模拟了联合,但增加了一些安全性,而且

基于索引的值访问器:如果v.Index()==I,则返回对存储在v中的值的引用否则,抛出std::bad\u variant\u访问。如果I不是变量中的有效索引,则调用的格式错误


但是,如果这种基本的东西失败了,它有什么好处呢


<> C++中的联盟从来没有被使用过。当您希望将两个或多个值压缩到同一内存中时(但在任何时候仅使用其中一个值),联合是为了节省内存。我从未遇到过它们的真正用例<代码> STD::变体不过,C++的添加很好。更大的情况是,很久以来就已经有了所谓的产品类型,比如
std::pair
,从这个意义上讲,它们可以表示的一组值是
T1 x T2
。使用<代码> STD::(和<代码> STD::任何< /代码>)现在C++也有适当的(=具有一个类型的类型安全性,您从未从联盟中得到)和类型,即值A组代码> STD::变体< /代码>可以表示是<代码> T1+T2< /Calp>(抱歉使用草率符号,希望它是清楚的)。p>
std::variant
是一个“类型安全联合”,这意味着它将检查您从中获得的是最后存储在其中的类型。在本例中,您正在存储一个
double
,但试图获取一个
uint64\u t

请参见此处的文档:

基于类型的值访问器:如果v持有可选的T,则返回对存储在v中的值的引用。否则,抛出std::bad_variant_访问。如果T不是类型的唯一元素,则调用的格式不正确


std::variant
是一个“类型安全联合”,这意味着它将检查您从中获得的是最后存储在其中的类型。在本例中,您正在存储一个
double
,但试图获取一个
uint64\u t

请参见此处的文档:

基于类型的值访问器:如果v持有可选的T,则返回对存储在v中的值的引用。否则,抛出std::bad_variant_访问。如果T不是类型的唯一元素,则调用的格式不正确


union
从来都不适合类型双关。读取不同于上次写入的工会成员始终是未定义的行为。变量中没有
uint64\u t
。为什么你希望它给你一个呢?你给它赋值一个双精度,然后把它读成一个整数。你期待什么?用一个联盟来做这件事,进入UB Lead,得到一个例外是异常好的。@ JuZLIN如果你想这样做,那么C++的方式是:<代码> MeMCPY 双UUT64 64 T。“但是如果这种基本的东西失败了,它有什么好处?”我认为这是一个成功的基本例子:->代码>联合< /代码>对于类型双关是不好的。读取不同于上次写入的工会成员始终是未定义的行为。变量中没有
uint64\u t
。为什么你希望它给你一个呢?你给它赋值一个双精度,然后把它读成一个整数。你期待什么?这样做是用一个联盟来进入UB Lead,这样得到一个异常就更好了。@ JuZLIN如果你想这样做,那么C++的方式是:<代码> MeMCPY 双UUT64 64 T。“但是如果这种基本的东西失败了,它有什么用?”我认为这是一个强大的ExCA。
terminate called after throwing an instance of 'std::bad_variant_access'
  what():  Unexpected index
Aborted (core dumped)