C++ 开关盒或std::map哪一种更有效

C++ 开关盒或std::map哪一种更有效,c++,parsing,tokenize,C++,Parsing,Tokenize,我在考虑这里的标记器。 每个令牌在解析器内调用不同的函数。 效率更高的是: std::functions/boost::functions的映射 开关箱 VisualStudio2008附带的STL映射将为每个函数调用提供O(log(n)),因为它隐藏了下面的树结构。 使用现代编译器(取决于实现),switch语句将给出O(1),编译器将其转换为某种查找表。 所以一般来说,切换速度更快 C++标准没有说明它的性能的要求,只是功能应该在那里。 这些关于哪个更好、更快或更高效的问题是毫无意义

我在考虑这里的标记器。
每个令牌在解析器内调用不同的函数。
效率更高的是:

  • std::functions/boost::functions的映射
  • 开关箱

    • VisualStudio2008附带的STL映射将为每个函数调用提供O(log(n)),因为它隐藏了下面的树结构。 使用现代编译器(取决于实现),switch语句将给出O(1),编译器将其转换为某种查找表。 所以一般来说,切换速度更快

      <强> <<强>,考虑以下事实:

      map和switch的区别在于:map可以动态构建,而switch不能。MAP可以包含任意类型的键,而开关非常受限于C++原语类型(char、int、eNUM等)。 顺便说一句,您可以使用哈希映射来实现接近O(1)的调度(不过,根据哈希表的实现,在最坏的情况下,它有时可能是O(n))。尽管如此,切换速度还是会更快

      编辑

      我写以下只是为了好玩和讨论的问题

      我可以为您提出一个很好的优化建议,但这取决于您的语言的性质以及您是否能够预期您的语言将如何使用

      编写代码时: 您将您的代币分为两组,一组使用频率非常高,另一组使用频率较低。您还可以对频繁使用的令牌进行排序。 对于高频率令牌,您编写一个if-else系列,使用频率最高的先到。对于使用频率较低的语句,可以编写switch语句

      其思想是使用CPU分支预测,以避免另一个间接级别(假设if语句中的条件检查几乎没有成本)。 在大多数情况下,CPU将选择正确的分支,而无需任何级别的间接寻址。然而,分支机构去错地方的情况很少。 根据你语言的性质,从统计上看,它可能会有更好的表现


      编辑:由于下面的一些评论,更改了一句话,告知编译器将始终将转换为LUT。

      您对“高效”的定义是什么?如果您的意思是更快,那么您可能应该分析一些测试代码以获得明确的答案。如果您想要灵活且易于扩展的代码,那么请帮自己一个忙,使用map方法。其他一切都只是过早的优化…

      您没有说您的令牌是什么类型的。如果它们不是整数,您就别无选择-开关仅适用于整数类型

      正如yossi1981所说,开关可以优化为快速查找表,但不能保证,每个编译器都有其他算法来确定是将开关实现为连续if还是快速查找表,或者两者的组合

      要获得快速切换,您的值应符合以下规则: 它们应该是连续的,例如0,1,2,3,4。您可以省略一些值,但是像0,1,2,34,43这样的值不太可能被优化

      问题是:在您的应用程序中,性能是否如此重要?
      从一个文件中动态地加载其值的映射不是一个更大的可读性和可维护性,而不是一个跨越多个代码页的大语句吗?

      < P> C++标准没有说明它的性能的要求,只是功能应该在那里。 这些关于哪个更好、更快或更高效的问题是毫无意义的,除非您陈述了您正在谈论的实现。例如,JavaScript的某个实现的某个版本中的字符串处理非常糟糕,但您不能将其推断为相关标准的一个特性

      我甚至可以说,无论实现如何,这都无关紧要,因为
      switch
      std::map
      提供的功能是不同的(尽管有重叠)

      在我看来,这些微优化几乎从来没有必要。

      我建议阅读Joel关于软件的文章。特别是,这一反应很有趣:

      “人们浪费时间的最好例子 尝试优化最小的 意义重大。”

      是和否。在虚拟机中,您通常 调用每个函数都非常有用的小函数 很少。这是电话号码,不是电话号码 这和序言一样伤害你 以及每个功能的清理例行程序 通常是一个很大的百分比 执行时间。这是 被研究到死,尤指被 已经实现线程化的人 口译员

      在虚拟机中,存储要调用的计算地址的查找表通常优先于交换机。(直接线程,或“标签为值”。直接调用存储在查找表中的标签地址)这是因为它允许在某些条件下减少,这在长流水线CPU中非常昂贵(它强制刷新管道)。然而,它使代码的可移植性降低

      这个问题已经在虚拟机社区进行了广泛的讨论,如果你想了解更多,我建议你寻找这个领域的学者论文。Ertl&Gregg在2001年就这个话题写了一篇很棒的文章

      但正如前面提到的,我非常确定这些细节与您的代码无关。这些都是小细节,你不应该太关注它。Python解释器正在使用开关,因为他们认为它使代码更具可读性。你为什么不选择你最喜欢的用法呢?性能影响将非常小,您最好现在关注代码的可读性;)

      编辑:如果重要的话,使用哈希表总是比查找表慢。查找