我正在研究RDDL的解析器,并且正如我之前所做的那样,当我定义包含我使用的类型的union时,我使用指针。 E.g。
%union {
double d;
int i;
std::string *str;
std::vector<std::string> *vectorStr;
RDDLBlock *rddlBlock;
Domain *domain;
DefineType *defineType;
std::vector<DefineType*> *vectorDefineType;
DomainList *domainList;
std::vector<PvarDefinition*> *vectorPvarDefinition;
PvarDefinition *pVarDefinition;
CpfDefinition *cpfDefinition;
std::vector<CpfDefinition*> *vectorCpfDefinition;
PvarExpression *pVarExpression;
LogicalExpression *logicalExpression;
std::vector<LogicalExpression*> *vectorLogicalExpression;
LConstCaseList *lConstCaseList;
CaseDefine *caseDefine;
std::vector<CaseDefine*> *vectorCaseList;
Parameter *parameter;
ParameterList *parameterList;
ObjectDefine *objectDefine;
std::vector<ObjectDefine*> *objectsList;
PvariablesInstanceDefine* pvariablesInstanceDefine;
std::vector<PvariablesInstanceDefine*> *pvariablesInstanceList;
Instance *instance;
NonFluentBlock *nonFluentBlock;
}
这是我看到大多数人在解析器中实现多个令牌类型的方式。在网上搜索这个答案时,我所看到的只是示例,并没有解释为什么我们必须使用指针。我现在的任务之一就是清理指针&#39;哪里有可能。所以我的问题是,在这种情况下,为什么我们(必须)在联合中使用指针?
编辑:添加了在union中定义的完整类型列表。
答案 0 :(得分:4)
您不必使用指针。如您所见,double
和int
都不是指针。
至于“我们为什么要使用”部分,我们应该记住union
的一些属性。
sizeof union_t
必须至少与最大会员一样大。所以你不希望联合使用一个单词int
和一些1KB的值。指针几乎总是固定的小尺寸。
在C ++世界中,许多类(对于您的示例,std::string
和std::vector
)具有非平凡的复制构造函数和析构函数。
对于这些类,将它们组合在一起是不安全的。 C ++ 11为此提供了一个“解决方案”,称为unrestricted unions。但即使这样,它也不会按原样运行:对于union_t object
的每次赋值和销毁,你必须明确地破坏/构造一个活跃的联盟成员。
答案 1 :(得分:1)
非平凡对象无法存储在联合中,因此只要使用%union
,就必须使用指针。但是,Bison 3提供了一种基于变体的替代方案,可以让您免于使用指针。
所以而不是
%union
{
int ival;
std::string* sval;
}
%token <ival> NUMBER;
%token <sval> STRING;
你会写
%define api.value.type variant
%token <int> NUMBER;
%token <std::string> STRING;
有关详情,请参阅Bison官方文档中的A Complete C++ Example。