【问题标题】:Handle object destruction on the stack处理堆栈上的对象销毁
【发布时间】:2012-11-21 23:08:32
【问题描述】:

我目前正在编写一个编译器前端,用于关于该主题的个人教育,我遇到了一个问题,涉及我通过运算符重载在 C++ 中处理 BNF 定义的方式。

目前我的设置如下:

规则.h:

class Rule
{
public:
    ChainRule operator>>(Rule& right);
    OrRule operator|(Rule& right);
    KleeneRule operator*();
    OptionalRule Rule::operator+();

    virtual bool parse(TokenList::iterator& begin, TokenList::iterator end) = 0;
};

规则.cpp:

ChainRule Rule::operator>>(Rule& right) {
    return ChainRule(this, &right);
}

OrRule Rule::operator|(Rule& right) {
    return OrRule(this, &right);
}

KleeneRule Rule::operator*() {
    return KleeneRule(this);
}

OptionalRule Rule::operator+() {
    return OptionalRule(this);
}

ChainRule、OrRule、KleeneRule、OptionalRule 和 EmptyRule 的定义很简单,如下所示:

class ChainRule : public Rule
{
private:
    Rule* next;
    Rule* _this;

public:
    ChainRule();
    ChainRule(Rule* _this, Rule* right);

    bool parse(TokenList::iterator& begin, TokenList::iterator end) override;
};

Rule 的每个子类显然都定义了 parse() 的合理实现。使用这些类,我可以如下定义我的语法:

OrRule assignment_exp   = logical_or_exp
                        | unary_exp >> StringRule("=") >> assignment_exp
                        ;   

现在问题来了:每个重载的运算符都按值返回一个新对象。这意味着每当我使用 operator>> 或 operator|从 Rule 类,一旦我从对 operator>> 或 operator| 的调用返回,这些指针将是垃圾。因为堆栈已被清理并且对象已消失。

我也不能在我的 Rule 子类的构造函数中使用按值传递,因为这不允许我定义递归语法。

所以我没有按值传递对象的选项,也没有通过指针传递对象的选项。谁能给我指出一个不会强迫我这样定义语法的解决方案?

StringRule s = StringRule("=");
OrRule assignment_exp;
ChainRule temp1 = s >> assignment_exp;
ChainRule temp2 = unary_exp >> temp1;
assignment_exp = logical_or_exp | temp2;

附:我知道各种解析器生成器和 Boost.Spirit,但我的目标是编写自己的解析器。

【问题讨论】:

    标签: c++ stack allocation bnf destruction


    【解决方案1】:

    您可以在堆上分配返回对象(通过工厂)并将它们作为引用返回。工厂可以跟踪它们,因此您不会泄漏。就语法而言,它与按值返回它们时的工作方式相同。

    【讨论】:

      【解决方案2】:

      您可以通过用包装器对象替换 Rule*(存在无法为它们重载运算符的问题)来解决此问题。 IE。 ChainRule 将包含 RuleRef next 而不是 Rule * next 等,并且所有运算符都将为 RuleRef 定义。 RuleRef 将仅包含 Rule*,并且可以从 Rule* 构造。为了使内存处理更容易,您可以从智能指针类继承。

      【讨论】:

        猜你喜欢
        • 2013-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-22
        • 2021-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多