从 boost::variant 获取整数生成分段错误
Get int from boost::variant generate segmentation fault
我正在尝试从 boost::variant 获取整数值。代码生成分段错误 - 为什么?
我在代码中添加了注释,哪些行会产生错误。我以为
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
我认为您误解了什么是 boost 变体。该库的文档将 variant
类型描述为 "multi-type, single value." (强调我的)。由于您分配了类型 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);
应该 return 一个空指针。取消引用空指针是未定义的行为,很可能是您的分段错误的原因。
我认为您正在寻找的行为在 tuple
中(在 boost 和 std 中都可以找到)。如果您不介意为成员对象命名,一个简单的 struct/class 也可以。
恐怕您不了解 boost::variant
是如何工作的。在类型论中,boost::variant
是 Sum 类型,或 Algebraic Data Type
.
这也经常被称为 "discriminated union" 并且基本上看起来像(在这种情况下):
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;
请注意,每次 index
表示 union
中哪个成员当前处于活动状态都会更新...因此 只有一个联合成员是在任何时间点活跃.
当您使用 boost::get<int>(&v)
时,代码实际如下所示:
int* get_0(Variant* v) {
if (v && v->index == 0) { return &v->u.a; }
return nullptr;
}
因此,由于此时 v->index
是 2
,它 returns 是 nullptr
。
唯一可用的 get
是 boost::get<std::string>(&v)
,因为它会检查 index
是否为 2
,它确实是 2
,因此 returns指向 v.u.c
.
的指针
我正在尝试从 boost::variant 获取整数值。代码生成分段错误 - 为什么? 我在代码中添加了注释,哪些行会产生错误。我以为
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
我认为您误解了什么是 boost 变体。该库的文档将 variant
类型描述为 "multi-type, single value." (强调我的)。由于您分配了类型 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);
应该 return 一个空指针。取消引用空指针是未定义的行为,很可能是您的分段错误的原因。
我认为您正在寻找的行为在 tuple
中(在 boost 和 std 中都可以找到)。如果您不介意为成员对象命名,一个简单的 struct/class 也可以。
恐怕您不了解 boost::variant
是如何工作的。在类型论中,boost::variant
是 Sum 类型,或 Algebraic Data Type
.
这也经常被称为 "discriminated union" 并且基本上看起来像(在这种情况下):
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;
请注意,每次 index
表示 union
中哪个成员当前处于活动状态都会更新...因此 只有一个联合成员是在任何时间点活跃.
当您使用 boost::get<int>(&v)
时,代码实际如下所示:
int* get_0(Variant* v) {
if (v && v->index == 0) { return &v->u.a; }
return nullptr;
}
因此,由于此时 v->index
是 2
,它 returns 是 nullptr
。
唯一可用的 get
是 boost::get<std::string>(&v)
,因为它会检查 index
是否为 2
,它确实是 2
,因此 returns指向 v.u.c
.