从 boost::variant 生成分段错误中获取 int

Get int from boost::variant generate segmentation fault

本文关键字:错误 获取 分段 int boost variant      更新时间:2023-10-16

我正在尝试从boost::variant中获取int值。代码生成分段错误 - 为什么?我将注释放在代码中,这些行会产生错误。我以为

int numberInt = boost::get<int>(v);

将无法正常工作,所以我将其更改为

int *ptrInt = boost::get<int>(&v);

哪个正在编译,但我仍然无法获得 int 值?与双倍完全相同。字符串类型正在工作。

#include <iostream>
#include "boost/variant.hpp"
#include <boost/variant/get.hpp>
using namespace std;
int main(int argc, char* argv[])
{
  boost::variant<int, double, std::string> v;
  v = 16;
  v = 3.1415;
  v = "hello new year";
  //int numberInt = boost::get<int>(v);     //1) not working
  //double numberDouble = boost::get<double>(v);//2) not working
  int *ptrInt = boost::get<int>(&v);        //3) compiling
  if(ptrInt) 
    cout << *ptrInt << endl;            //4) not displayed
  //cout << *ptrInt << endl;            //5) segmentation fault
  double *ptrDouble = boost::get<double>(&v);   //6) compiling
  if(ptrDouble) 
    cout << *ptrDouble << endl;         //7) not displayed
  //cout << *ptrDouble << endl;         //8) segmentation fault
  std::string caption = boost::get<string>(v);
  cout << caption << endl;          //9) working
  return 0;
}
// clear && clear && g++ test.cpp -std=c++11 -o test && ./test

我想你误解了什么是提升变体。库的文档将variant类型描述为"多类型,单个值"。(强调我的)。由于您已经分配了类型 std::string 的值,因此不会在variant中存储其他类型的值。variant的一个好处(与union相比)在get函数的注释中有所描述:

// Retrieves content of given variant object if content is of type T.
// Otherwise: pointer ver. returns 0; reference ver. throws bad_get.

因此,如果int numberInt = boost::get<int>(v);正常工作,它应该引发异常。int *ptrInt = boost::get<int>(&v);应该返回一个空指针。取消引用空指针是未定义的行为,可能是分段错误的原因。

我认为您正在寻找的行为是tuple(在 boost 和 std 中都有)。如果您不介意为成员对象命名,一个简单的结构/类也可以。

怕你不明白boost::variant是如何工作的。在类型论中,boost::variant是和类型,或Algebraic Data Type

这通常也被称为"歧视工会",基本上看起来像(在这种情况下):

struct Variant {
    size_t index;
    union {
        int a;
        double b;
        std::string c;
    } u;
};

现在,当你写v = 16时,会发生什么是:

v.u.a = 16; v.index = 0;

当你写v = 3.1415时,会发生什么是:

v.u.b = 3.1415; v.index = 1;

最后,当你写v = "hello new year"时,发生的事情是:

v.u.c = "hello new year"; v.index = 2;

请注意,每次都会更新表示当前处于活动状态的union成员的index...因此,在任何时间点,只有一个工会成员处于活跃状态。

当您使用boost::get<int>(&v)代码实际上如下所示:

int* get_0(Variant* v) {
    if (v && v->index == 0) { return &v->u.a; }
    return nullptr;
}

因此,由于此时v->index2的,因此它返回一个nullptr

唯一有效的getboost::get<std::string>(&v),因为它检查index是否2,因此返回指向v.u.c的指针。