C++ 在解析器文件中定义联合时,为什么要对复杂类使用指针?
我正在为开发一个解析器,正如我以前所做的那样,当我定义包含我使用的类型的union时,我使用指针。例如C++ 在解析器文件中定义联合时,为什么要对复杂类使用指针?,c++,pointers,bison,unions,C++,Pointers,Bison,Unions,我正在为开发一个解析器,正如我以前所做的那样,当我定义包含我使用的类型的union时,我使用指针。例如 %union { double d; int i; std::string *str; std::vector<std::string> *vectorStr; RDDLBlock *rddlBlock; Domain *domain; DefineType *defineType; std::vector<D
%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;
}
%union{
双d;
int i;
std::string*str;
std::vector*vectorStr;
RDDLBlock*RDDLBlock;
域*域;
DefineType*DefineType;
std::vector*vectorDefineType;
域名列表*域名列表;
std::vector*vectorPvarDefinition;
PvarDefinition*PvarDefinition;
CPFD定义*CPFD定义;
std::vector*VectorCPFD定义;
PvarExpression*PvarExpression;
LogicalExpression*LogicalExpression;
std::vector*vectorLogicalExpression;
LConstCaseList*LConstCaseList;
CaseDefine*CaseDefine;
标准::矢量*矢量病例表;
参数*参数;
参数列表*参数列表;
ObjectDefine*ObjectDefine;
std::vector*objectsList;
PvariablesInstanceDefine*PvariablesInstanceDefine;
std::vector*pvariablesInstanceList;
实例*实例;
非流块*非流块;
}
这就是我看到大多数人在解析器中实现多种令牌类型的方式。在网上搜索这个答案时,我看到的只是一些例子,没有解释为什么我们必须使用指针。我现在的任务之一就是在可能的地方“清理指针”。所以我的问题是,在这种情况下,为什么我们(必须)在联合中使用指针
编辑:添加了union中定义的类型的完整列表。您不必使用指针。如您所见,
double
和int
都不是指针
至于“我们为什么使用”部分,我们应该记住union
的一些属性
int
和一些1KB的值类合并。指针几乎总是有固定的小尺寸对于这样的类,将它们合并是不安全的。C++11为此提供了一个“解决方案”,称为。但即使这样,它也不会按原样工作:对于
联合对象的每次赋值和销毁,您必须显式地销毁/构造一个活动的联合成员。您不必使用指针。如您所见,double
和int
都不是指针
至于“我们为什么使用”部分,我们应该记住union
的一些属性
工会的大小必须至少与最大成员的大小相同。因此,您不希望与单个单词int
和一些1KB的值类合并。指针几乎总是有固定的小尺寸
<> L> >P>在C++世界中,很多类(对于您的例子, STD::String 和)具有非平凡的复制构造函数和析构函数。
对于这样的类,将它们合并是不安全的。C++11为此提供了一个“解决方案”,称为。但即使这样,它也不会按原样工作:对于联合对象的每次赋值和销毁,您必须显式地销毁/构造活动的联合成员。非平凡对象不能存储在联合中,因此只要您使用%union
,就必须使用指针。然而,Bison3提供了一个基于变体的替代方案,它使您不必使用指针
所以不是
%union
{
int ival;
std::string* sval;
}
%token <ival> NUMBER;
%token <sval> STRING;
%union
{
国际竞争力;
std::string*sval;
}
%令牌号;
%令牌串;
你会写信吗
%define api.value.type variant
%token <int> NUMBER;
%token <std::string> STRING;
%define api.value.type变量
%令牌号;
%令牌串;
有关详细信息,请参阅Bison文档中的。非平凡对象不能存储在联合中,因此只要使用%union
,就必须使用指针。然而,Bison3提供了一个基于变体的替代方案,它使您不必使用指针
所以不是
%union
{
int ival;
std::string* sval;
}
%token <ival> NUMBER;
%token <sval> STRING;
%union
{
国际竞争力;
std::string*sval;
}
%令牌号;
%令牌串;
你会写信吗
%define api.value.type variant
%token <int> NUMBER;
%token <std::string> STRING;
%define api.value.type变量
%令牌号;
%令牌串;
有关更多详细信息,请参阅Bison文档中的。如果您不知道为什么必须这样做,则可能不必这样做,因为解析堆栈中没有大量元素。如果你的元素不是很大,那就不用麻烦了
,Domain*Domain
。@LưuVĩnhPhúc这也是要做的更改之一。@EJP切换到非指针类型的主要原因不是到处都是指针,而是到处都是对象实例。如果你不知道为什么要这样做,您可能不必这样做,因为解析堆栈上没有大量元素。如果你的元素不是很大,那就不用麻烦了
,Domain*Domain
。@LưuVĩnhPhúc这也是要做的更改之一。@EJP切换到非指针类型的主要原因不是有一堆指针,而是有一堆对象实例。谢谢你的回答!在我把它标记为正确之前,我想问一个小问题。由于我的联合体中既有std::string类型,也有std::vector类型(我将用完整的类型列表更新问题),这将取决于编译器,因此不是每个人都能用默认编译器编译它。该项目在完成后将是开放源代码的,在没有许多额外设置的情况下准备好运行和编译是很重要的。@Đ或đeRelić,我错了,它现在是标准的。但是,有很多注意事项——你需要仔细考虑每个拷贝、赋值和销毁<代码>联合< /COD>对象。在我看来,这不值得努力,最好把指针留在原地。谢谢你的回答!在我把它标记为正确之前,我想问一下