【问题标题】:Get int from boost::variant generate segmentation fault从 boost::variant 获取 int 生成分段错误
【发布时间】:2015-01-03 13:02:10
【问题描述】:

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

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

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

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

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

#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

【问题讨论】:

    标签: c++ boost get int boost-variant


    【解决方案1】:

    我认为您误解了什么是 boost 变体。该库的文档将variant 类型描述为“多类型,单值”。 (强调我的)。由于您分配了std::string 类型的值,因此variant 中没有存储其他类型的值。 variant 的一个优点(与 union 相比)在 get 函数的 cmets 中有所描述:

    // 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&lt;int&gt;(v); 工作正常,它应该抛出一个异常。 int *ptrInt = boost::get&lt;int&gt;(&amp;v); 应该返回一个空指针。取消引用空指针是未定义的行为,很可能是您的分段错误的原因。

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

    【讨论】:

      【解决方案2】:

      恐怕你不明白boost::variant 是如何工作的。在类型论中,boost::variant 是 Sum 类型,或 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&lt;int&gt;(&amp;v) 时,代码实际上如下所示:

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

      因此,由于此时v-&gt;index2,它返回一个nullptr

      唯一可以工作的getboost::get&lt;std::string&gt;(&amp;v),因为它会检查index 是否是2,因此返回一个指向v.u.c 的指针。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-03
        • 1970-01-01
        • 2014-01-25
        • 2015-12-22
        相关资源
        最近更新 更多