前两天看到了这个用法。
感觉这个关键词感觉还是挺误导人的。
因为我一开始以为,在每次销毁token的时候都会调用这个destructor。因为我的token有的会带有指针类型的值,但却并不是所有匹配规则都会用到这个指针指向的值。所以我以为只要设置了destructor,在每次匹配成功一个规则的时候,就不用手动去释放没有用到的token了。结果并!没!有!
原来,这个destructor,只有在发生错误,要扔掉token的时候才会被调用。
比如:
%union{
int* i;
}
%token<i> INT
%destructor { delete $$; } <i>
%%
rule1: INT '+' INT
{
$$ = $1;
*($$) += *($3);
delete $3;
$1 = $3 = nullptr;
}
假设其中token INT为匹配一个整型。
那么当输入为1 + 3
的时候,成功匹配到规则rule1的时候,destructor并不会被调用。此时必须手动释放$3指针指向的空间。
但是如果输入为3 - 1
的时候,减号-
匹配失败,发生错误,此时栈中的两个token:INT和‘-’会被扔掉,此时,在扔掉INT token的时候,才会调用对应的destructor。
所以,destructor其实是用来防止发生错误时可能导致的内存泄漏。