【问题标题】:Holding a map reference to a vector of maps持有对地图矢量的地图引用
【发布时间】:2019-05-17 09:59:10
【问题描述】:

我的任务是构建一个编译器,对生成的抽象语法树进行词法分析、解析和分析,以确保类型匹配、避免重复声明等。

我们被指示构建一个符号表,其中包含每个范围的变量及其类型的映射。我选择了地图矢量。我更喜欢它而不是堆栈,因为我可以在任何范围内检查变量时对其进行迭代。

我为这个结构构造了 Push、Pop、Lookup 和 Insert 操作,如下所示,我的想法是在向量​​中保存对最新映射的引用并向其中添加变量。进入新范围时,会执行推送操作,在存储数组的向量中创建一个新映射。

当一个范围退出时,会执行 Pop 操作以删除向量末尾的映射并获取现在位于向量后面的前一个映射。

通过调试,我注意到该向量根本不包含地图详细信息,并且通过引用工作似乎没有做任何事情来更新应该包含此地图的向量。如何正确引用矢量内的地图并维护此结构?

符号表:

struct SymbolTable {
        // Stack defining scopes holding identifier / type details
        std::vector<std::map<std::string,std::string>> _scopeVector;

        // Tracks current working stack
        std::map<std::string,std::string> _currentMap;

        SymbolTable() = default;

        void Push() {
            std::map<std::string,std::string> *_tempMap;
            _tempMap = new std::map<std::string,std::string>();
            _scopeVector.push_back(*_tempMap);
            _currentMap = _scopeVector.back();
        }

        void Insert(std::string p_name, std::string p_type) {
            _currentMap.insert(std::make_pair(p_name,p_type));
        }

        // Returns type if found, empty if not
        std::string Lookup (std::string p_name) {
            for (int i = 0; i < _scopeVector.size(); i++) {
                if (_scopeVector[i].find(p_name) == _scopeVector[i].end()) {
                    // No match yet
                } else {
                    return _scopeVector[i].find(p_name)->first; // return var name
                }
            }
            std::cerr << "Type name " << p_name << " not found in all of stack" << std::endl;
            return "";
        }

        void Pop () {
            _scopeVector.pop_back();
            _currentMap = _scopeVector.back();
        }
    };

    SymbolTable *ST;

设置符号表的类构造函数:

SemanticAnalysisVisitor() {
    ST = new SymbolTable();
    ST->Push();
}

Debugger image of an empty vector but populated map

【问题讨论】:

  • 您有内存泄漏。您动态分配了一个新地图,但您从未释放它。
  • @Someprogrammerdude 在这种情况下会添加 delete _scopeVector.back() 工作吗?
  • 不,不是您显示的当前代码。那是因为_scopeVector.push_back(*_tempMap) 也复制了地图!你需要delete tempMap(或者正如我在回答中建议的那样推送指针本身,在这种情况下你可以在Pop函数中删除它)。

标签: c++ compiler-construction semantic-analysis


【解决方案1】:

至于你的问题(我认为)声明

_currentMap = _scopeVector.back();

复制来自矢量的地图。

_currentMap 将始终是一个单独且不同的映射,与向量中的任何内容完全无关。

您似乎想使用引用,但在这种情况下这是不可能的(除非您进行重新设计)。

您可以通过使用指向地图的(智能)指针向量来解决这个问题(以及我在评论中提到的内存泄漏),并将_currentMap 也设为(智能)指针。

【讨论】:

  • 我看到智能指针不是通常使用的 foo* 而是类似 unique_ptr<:map>> 的东西?将向量更改为地图指针并在整个代码中更新它似乎并没有解决我的问题,它们仍然是分离的:std::vector<:map>*> _scopeVector;
  • @Luponius 您还记得将_currentMap 更新为指针吗?在这种情况下,std::shared_ptr 将是更好的选择,或者可能是非拥有(原始、普通和标准)指针。
  • 你是对的,而不是将 currentMap 设置为指针,我取消了 back() 结果的引用。
猜你喜欢
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-24
  • 1970-01-01
相关资源
最近更新 更多