我有一个内存管理问题。对于one of my projects我正在为一种小型编程语言构建一个解释器。最初的步骤之一是建模和构建Abstract Syntax Tree。
截至目前,我正在使用智能指针管理节点的生命周期,我认为每个父节点都是其子节点的所有者,但它也必须与环境共享(例如,要知道方法的主体所属的树的哪一部分)和垃圾收集器,垃圾收集器必须保留所有引用的列表以实现初始标记和扫描算法。因此,我使用std::shared_ptr
来跟踪引用。例如,这是一个Block
节点的示例,它基本上代表一个lambda表达式:
#ifndef NAYLANG_BLOCK_H
#define NAYLANG_BLOCK_H
#include <model/ast/expressions/Expression.h>
#include <model/ast/declarations/Declaration.h>
#include <memory>
#include <vector>
namespace naylang {
#define BlockPtr std::shared_ptr<Block>
class Block : public Expression {
std::vector<std::shared_ptr<Statement>> _body;
std::vector<std::shared_ptr<Declaration>> _params;
public:
Block() = default;
void accept(Evaluator &evaluator) override;
const std::vector<std::shared_ptr<Statement>> &body() const;
const std::vector<std::shared_ptr<Declaration>> ¶ms() const;
void addStatement(std::shared_ptr<Statement> statement);
void addParameter(std::shared_ptr<Declaration> param);
};
} // end namespace naylang
#endif //NAYLANG_BLOCK_H
如您所见,此节点是其所有参数和正文表达式的所有者,并具有访问器,以便Evaluator
可以遍历树。
现在,当尝试将在评估时绑定到其他节点的节点时出现问题,例如:
#ifndef NAYLANG_REQUEST_H
#define NAYLANG_REQUEST_H
#include <model/ast/expressions/Expression.h>
#include <string>
#include <memory>
#include <vector>
#include <model/ast/declarations/MethodDeclaration.h>
namespace naylang {
class Request : public Expression {
std::string _name;
std::vector<ExpressionPtr> _params;
// We use naked pointers because we don't want to worry
// about memory management, and there is no ownership
// with the declaration.
const MethodDeclaration *_binding;
public:
Request(const std::string &methodName);
Request(const std::string &methodName, const std::vector<ExpressionPtr> params);
void accept(Evaluator &evaluator) override;
void bindTo(const MethodDeclaration *_binding);
const std::string &method() const;
const std::vector<ExpressionPtr> ¶ms() const;
const MethodDeclaration &declaration() const;
};
} // end namespace naylang
#endif //NAYLANG_REQUEST_H
如您所见,bindTo()
(BindingEvaluator
的子类)在构造之后很久就会对Request对象进行求值时调用Evaluator
。但是,我真的不确定_binding
参数应该是什么样子。这是Evaluator
界面的一部分:
#ifndef NAYLANG_EVALUATOR_H
#define NAYLANG_EVALUATOR_H
#include <model/ast/Statement.h>
namespace naylang {
class Request;
class Block;
class Evaluator {
public:
Evaluator() = default;
virtual ~Evaluator() = default;
// Methods left blank to be overridden by the subclasses.
// For example, a Binding Evaluator might be only interested in
// evaluating VariableReference and Request Statements
virtual void evaluate(Request &expression) {}
virtual void evaluate(Block &expression) {}
};
}
#endif //NAYLANG_EVALUATOR_H
这是我的理由:
std::shared_ptr
。 void accept(Evaluator &evaluator);
。由于节点无法返回shared_ptr
自身,因此我们无法将界面更改为virtual void evaluate(std::shared_ptr<Request> &expression) {}
。提前谢谢。