C ++ STL Map vs Vector speed

时间:2010-04-03 21:07:33

标签: c++ stl vector map

在我的实验性编程语言的解释器中,我有一个符号表。每个符号由一个名称和一个值组成(值可以是例如:string,int,function等类型。)

首先,我用一个向量表示该表,并通过符号迭代检查给定的符号名称是否合适。

然后我使用地图(在我的情况下为map<string,symbol>)比在 完整地迭代矢量更好:

解释这部分有点难,但我会尝试。

如果在我的语言的程序中第一次检索变量,当然必须找到它在符号表中的位置(现在使用vector)。如果我每次执行该行时都会迭代向量(想到一个循环),那么它将非常慢(因为它目前是,几乎和microsoft的批处理一样慢)。

所以我可以使用地图来检索变量:SymbolTable[ myVar.Name ]

但请注意以下几点:如果第一次找到仍使用向量的变量,我可以将它的精确整数位置存储在向量中。这意味着:下次需要时,我的翻译人员知道它已被“缓存”并且不会在符号表中搜索它,而是执行SymbolTable.at( myVar.CachedPosition )之类的操作。

现在我的(相当难的?)问题:

  • 我是否应该使用矢量作为符号表并缓存矢量中变量的位置?

  • 我应该使用地图吗?为什么? []运算符的速度有多快?

  • 我应该使用完全不同的东西吗?

12 个答案:

答案 0 :(得分:17)

地图是用于符号表的好东西。但地图的operator[]不是。通常,除非您编写一些简单的代码,否则应使用地图的成员函数insert()find()而不是operator[]operator[]的语义有点复杂,如果您要查找的符号不在地图中,几乎肯定不会做您想要的。

至于mapunordered_map之间的选择,在实施简单的解释性语言时,性能的差异极不可能显着。如果使用map,则保证所有当前的标准C ++实现都支持它。

答案 1 :(得分:13)

你实际上有很多选择。

存在库

<强>评论家

  • 使用O(log N)映射查找和检索,但这些项目可能分散在整个内存中,因此无法很好地使用缓存策略。
  • Vector对缓存更友好,但除非您对其进行排序,否则O(N)上的find性能会被接受,是否可以接受?
  • 为什么不使用unordered_map?它们提供O(1)查找和检索(尽管常量可能很高)并且当然适合于此任务。如果您查看维基百科关于Hash Tables的文章,您会发现有很多可用的策略,您当然可以选择一个适合您特定使用模式的策略。

答案 2 :(得分:4)

通常情况下,您会使用符号表来查找源名称中显示的名称变量。在这种情况下,您只能使用名称,因此无法在变量符号表中存储变量的缓存位置。所以我会说map是一个不错的选择。 []运算符需要的时间与映射中元素数量的对数成比例 - 如果结果很慢,则可以使用像std::tr1::unordered_map这样的哈希映射。

答案 3 :(得分:2)

std :: map的operator []占用O(log(n))时间。这意味着它非常有效,但您仍然应该避免一遍又一遍地进行查找。您可以存储对该值的引用,还是存储容器的迭代器,而不是存储索引?这避免了必须完全进行查找。

答案 4 :(得分:2)

当大多数解释器解释代码时,他们首先将其编译成中间语言。这些中间语言通常通过索引或指针引用变量,而不是名称。

例如,Python(C实现)通过索引将局部变量更改为引用,但全局变量和类变量使用哈希表通过名称引用。

我建议查看关于编译器的介绍性文本。

答案 5 :(得分:1)

a std::map(O(log(n)))或散列表(“摊销”O(1))将是第一选择 - 如果确定它是瓶颈,则使用自定义机制。通常,使用散列或标记输入是第一个优化。

在对其进行分析之前,最重要的是隔离查找,以便您可以轻松地替换和分析它。


std::map对于少数元素来说可能稍微慢一点(但是,它并不重要)。

答案 6 :(得分:0)

Map是O(log N),因此不如数组中的位置查找快。但确切的结果将取决于很多因素,因此最好的方法是以允许您稍后在实现之间交换的方式与容器交互。也就是说,编写一个“查找”函数,可以通过任何合适的容器有效地实现,以允许自己切换和比较不同实现的速度。

答案 7 :(得分:0)

Map的operator []是O(log(n)),参见维基百科:http://en.wikipedia.org/wiki/Map_(C%2B%2B)

我认为,当你经常寻找符号时,使用地图肯定是正确的。也许哈希地图(std::unordered_map)可以使您的表现更好。

答案 8 :(得分:0)

如果您要使用vector并且遇到缓存最新符号查找结果的麻烦,如果您的符号表可以执行相同的操作(缓存最新的查找结果)实现为map(但在使用map的情况下,缓存可能不会有很多好处)。使用map,您可以获得额外的优势,即任何非缓存符号查找都比在vector中搜索更高效(假设vector未排序 - 如果你不得不多次进行排序,保持矢量排序可能会很昂贵。

Neil's advice; map通常是符号表的良好数据结构,但您需要确保正确使用它(而不是意外添加符号)。

答案 9 :(得分:0)

你说:“如果第一次找到仍然使用向量的变量,我可以用它存储它在矢量中的确切整数位置。”。

您可以对地图执行相同操作:使用find搜索变量并存储指向它的iterator而不是位置。

答案 10 :(得分:0)

为了查找值,通过字符串键,地图数据类型是合适的,如其他用户所述。

STL地图实现通常使用self-balancing trees实现,就像red black tree数据结构一样,并且它们的操作需要O(logn)时间。

我的建议是将表操作代码包装在函数中,
例如table_has(name)table_put(name)table_get(name)

通过这种方式,您可以轻松更改内部符号表表示 运行时间性能较慢,此外您可以在以后嵌入这些例程缓存功能。

答案 11 :(得分:0)

地图将扩展得更好,这将是一个重要的功能。但是,不要忘记在使用地图时,您可以(与矢量不同)获取指针和引用。在这种情况下,您可以使用地图轻松地“缓存”变量,就像向量一样有效。地图几乎肯定是这里的正确选择。