如何制作高效的C++跳台

How to make efficient C++ jump table?

本文关键字:C++ 跳台 高效 何制作      更新时间:2023-10-16

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

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

#include <cstdio>
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
void Zero() { printf("Zeron"); }
void One() { printf("Onen"); }   
void Two() { printf("Twon"); }
void Three() { printf("Threen"); }
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;
}

switch 语句怎么样?

switch (c) {
   case 0:
      printf("Zeron"); break;
   case 1:
      printf("Onen"); break;
   case 2:
      printf("Twon"); break;
   case 3:
      printf("Threen"); break;
   default:
      break;
}

如果不采用开关解决方案,你就无能为力,无法使代码"更快",这打破了拥有函数数组的原始想法。如果你只要使用"字符",如'0' =>'9', 'a' => 'z',你可以躲避字符串所需的内存分配,你也可以用一个initializer_list初始化你的map,如果可行的话,你也可以使这样的数组常量静态。

如果有帮助,这是我的"优化"代码。

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;
}

请求为您的效率案例提供更多细节。您的意思是内存/CPU 周期/直通吗?根据您的代码:

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

就更底层的控制而言,您可以自定义哈希函数和自定义哈希表实现。在某些数据上,考虑std::map或排序std::vector选项可能是有用的。

由于静态查找速度很快,因此无论编译器如何,这都将执行得非常好。跳转表因编译器而异。我会使用以下代码,可能有些人会反对这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("%sn", choice_str[atoi(c)]);
         }
}