如何制作高效的C ++跳转表?

时间:2016-02-07 16:58:33

标签: c++ arrays dictionary

我是C ++的初学者,我已经实现了以下简单的跳转表,但我想知道我是否采用了正确的方法。无论如何我可以改进以下代码吗?

以下代码使用字典(我来自C#背景)来存储函数'指针。

#include <cstdio>
#include <iostream>
#include <string>
#include <unordered_map>

using namespace std;

void Zero() { printf("Zero\n"); }
void One() { printf("One\n"); }   
void Two() { printf("Two\n"); }
void Three() { printf("Three\n"); }

string prompt()
{
    printf("Enter number from 0 to 3 or q to quit:\n");
    string line;
    getline(cin, line);

    return line;
}

int main(int argc, const char * argv[]) {

    unordered_map<string, void(*)()> map;

    map["0"] = Zero;
    map["1"] = One;
    map["2"] = Two;
    map["3"] = Three;

    while (true) {
        string c = prompt();
        if (c == "q") break;

        map[c]();
    }
    return 0;
}

4 个答案:

答案 0 :(得分:6)

切换声明怎么样?

switch (c) {
   case 0:
      printf("Zero\n"); break;
   case 1:
      printf("One\n"); break;
   case 2:
      printf("Two\n"); break;
   case 3:
      printf("Three\n"); break;
   default:
      break;
}

答案 1 :(得分:3)

请提供更多有关效率的详细信息。你的意思是内存/ CPU周期/传递? 根据你的代码:

  • 它不容易出错(使用auto it = map.find(key);函数进行搜索并检查输出it != map.end()值,因此不会创建新元素。
  • 对于字符串键类型
  • 来说已经足够了
  • 通过用std::function<void()>
  • 替换函数指针,您可以轻松地提高灵活性

更低级别控制的术语你可以自定义散列函数和自定义散列表实现。 对于某些数据,将std::mapstd::vector作为选项进行考虑可能会很有用。

答案 2 :(得分:3)

您可以做的事情并不多,可以让您的代码快速生成#34;没有采用开关解决方案,这打破了拥有一系列功能的原始想法。如果你只打算使用'#39;字符&#39;例如&#39; 0&#39; =&GT; &#39; 9&#39;,&#39; a&#39; =&GT; &#39; Z&#39;你可以躲避字符串所需的内存分配,你也可以使用initializer_list初始化你的地图,如果可行,你也可以使这个数组const静态。

这是我的&#34;优化&#34;代码,如果它有帮助。

inline char prompt() //this function will probably 900% be inlined even if you don't specify the inlike keyword
{
    printf("Enter number from 0 to 3 or q to quit:\n");
    char v;
    while (!(std::cin >> v)); //Just to make sure we get valid input
    return v;
}

int main()
{
    static const std::unordered_map<char, void(*)()> mymap = 
    {
        { '0' , Zero },
        { '1' , One },
        { '2' , Two },
        { '3' , Three }
    };

    while(1)
    {
        auto it = mymap.find(prompt());

        // Without this check, your program will crash if input is invalid.
        if (it != mymap.end()) 
        {
            it->second();
            break;
        }
    }

    return 0;
}

答案 3 :(得分:1)

由于静态查找快速,无论编译器如何,这都会表现得非常好。跳转表与编译器不同。我会使用以下代码,可能有些人会反对这一点,因为global是坏的。但在发表评论之前,请评估一下

string prompt()
{
     printf("Enter number from 0 to 3 or q to quit:\n");
     string line;
     getline(cin, line);

     return line;
}

enum Choice = {ZERO = 0, ONE, TWO, THREE};

static char *choice_str[] = {
     "Zero",
     "One",
     "Two",
     "Three"
};

int main(int argc, const char * argv[]) {
    while (true) {
        string c = prompt();
        if (c == "q") 
        {
            break;
         }
         else {
              assert(atoi(c) >= Choice::ZERO && atoi(c) <=Choice::THREE);
              printf("%s\n", choice_str[atoi(c)]);
         }
}