C++ 代码优化;切换与if';s

C++ 代码优化;切换与if';s,c++,if-statement,switch-statement,optimization,C++,If Statement,Switch Statement,Optimization,我有一个问题,关于在一个经常被调用的函数中使用“case”还是“ifs”。 以下是“如果”中现在的情况;代码是不言自明的: int identifyMsg(char* textbuff) { if (!strcmp(textbuff,"text")) { return 1; } if (!strcmp(textbuff,"name")) { return 2; } if (!strcmp(textbuff,"list")) { return 3; } if (!strcm

我有一个问题,关于在一个经常被调用的函数中使用“case”还是“ifs”。 以下是“如果”中现在的情况;代码是不言自明的:

int identifyMsg(char* textbuff) {
if (!strcmp(textbuff,"text")) {
    return 1;
}
if (!strcmp(textbuff,"name")) {
    return 2;
}
if (!strcmp(textbuff,"list")) {
    return 3;
}
if (!strcmp(textbuff,"remv")) {
    return 4;
}
if (!strcmp(textbuff,"ipad")) {
    return 5;
}
if (!strcmp(textbuff,"iprm")) {
    return 6;
}
return 0;
}

我的问题是:交换机的性能会更好吗?我知道如果使用“如果”,我可以将最有可能的选项放在顶部

不能对字符串使用
switch
语句,因为它们是指针,在编译时不会求值。 您不得不使用一堆
if
语句

然而,为了性能起见,我相信当有更多的条件需要检查时,开关的性能会更好,但是差异会很小,这无关紧要

虽然我以前从未测试过,但我读过这种开关优化:

switch (value) {
  case frequent_value1:
  case frequent_value2:
  case frequent_value3:
    break;

default:
  switch (value) {
     case infrequent_value1:
     case infrequent_value2:
     case infrequent_value3:
        break;
     }
}
您可以使用生成想要查看的“动词”的完美哈希。然后可以使用
开关
语句

或者,你可以这样做:

switch (textbuff[0])
{
    case 'i':
    {
        switch (textbuff[1])
        {
            case 'p':
            {
                 switch (textbuff[2])
                 {
                     case 'a': /* something. */ break;
                     case 'r': /* something else. */ break;
                 }
            }
        }
    }
(你明白了)

作为另一个选项(如果所有命令都是4个字符),请将它们转换为单个32位数字,然后打开该选项:

int32_t mashed =
    textbuff[0] << 24 | 
    textbuff[1] << 16 |
    textbuff[2] << 8 |
    textbuff[3];

switch (mashed) { /* ... */ }
int32\t混搭=

textbuff[0]您可以很好地对这些字符串使用“enum”。然后使用switch case语句。

我最近遇到的另一个可能适合您的选择是:

int identifyMsg(const char* textbuff) {
    static const struct { const char* str; int id; } pairs[] = {
        { "text", 1 },
        { "name", 2 },
        { "list", 3 },
        { "remv", 4 },
        { "ipad", 5 },
        { "iprm", 6 },
    };
    for (int i = 0; i < sizeof(pairs)/sizeof(pairs[0]); ++i) {
        if (!strcmp(textbuff, pairs[i].str))
            return pairs[i].id;
    }
    return 0;
}
int identifymg(const char*textbuff){
静态常量结构{const char*str;int id;}对[]={
{“文本”,1},
{“名称”,2},
{“列表”,3},
{“remv”,4},
{“ipad”,5},
{“iprm”,6},
};
对于(int i=0;i
据我所知,有两个问题。优化和if/switch

首先,代码优化是一个代价高昂的过程。只优化代码中那些显而易见的瓶颈部分。在这种情况下,我对此表示怀疑。看起来,您正在发送一个文本id,以决定如何处理消息。这个信息来自哪里?IPC,XML,文件?你打算怎么处理这个消息?消息内容处理代码的性能如何?代码中应该有比字符串比较占用更多资源的位置

您是否试用过一些性能分析器,如Purify、gperf、cachegrind


关于if/switch:switch仅适用于整数类型。(char、short、int、long、enum)

假设它真的很重要:

因为strcmp很慢,但是整数比较很快:如果所有的命令都是4个字符长的(正好适合32位整数),那么可以将每个字符串转换为32位数字,然后根据该数字进行切换

否则,有两种基本方法可以快速将字符串与许多候选字符串进行比较:

  • 将候选项存储在哈希表中

  • 按数组中的字母顺序对候选项进行排序。然后,您可以使用strcmp的结果对数组执行二进制搜索,以查找匹配项,或排除剩余候选项的一半


另一方面,MSVC和GCC等编译器对交换机进行了优化,使用二进制搜索测试交换机条件。因此,一个包含256个元素的switch语句将被优化到最多8个比较操作。

您可以将所有值放入std::map

class MessageMap
{ 
    std::map<std::string,int>    data;
    public:
        MessageMap()
        {
             data["text"]   = 1;
             data["name"]   = 2;
             data["list"]   = 3;
             data["remv"]   = 4;
             data["ipad"]   = 5;
             data["iprm"]   = 6;
        }
        int getMessageId(std::string const& index) cosnt
        {
            std::map<std::string,int>::const_iterator f;
            if ((f = data.find(index)) != data.end())
            {
                return f->second;
            }
            return 0;
        }
};
int identifyMsg(char* textbuff)
{
    static MessageMap   mssageMap;
    return messageMap.getMessageId(textbuff);
}
class消息映射
{ 
地图数据;
公众:
MessageMap()
{
数据[“文本”]=1;
数据[“名称”]=2;
数据[“列表”]=3;
数据[“remv”]=4;
数据[“ipad”]=5;
数据[“iprm”]=6;
}
int getMessageId(std::string const&index)cosnt
{
std::map::const_迭代器f;
如果((f=data.find(index))!=data.end())
{
返回f->second;
}
返回0;
}
};
int identifyMsg(char*textbuff)
{
静态消息映射mssageMap;
返回messageMap.getMessageId(textbuff);
}

的确如此。但除此之外,“哪一个性能更好”的问题即使可能也没有意义。关于SO的另一个好话题是:那些嵌套开关不应该对性能产生任何积极影响。如果经常发生其中一种情况,则不会检查任何其他情况的条件。常规的if-elseif也是如此。不过,有许多技巧涉及到哈希和代码生成器,它们可以为字符串启用开关。在我看来,不值得这么麻烦,除非分析表明特定部分的性能是一个真正的问题。请看:在担心微观优化之前,您应该集中精力使代码正确。一旦它是正确的,你应该在优化之前进行测量。然后,当您认为需要优化时,您应该仔细考虑优化代码的未来可维护性。简言之,优化不正确的代码是没有意义的。生成哈希,然后使用开关不是太多吗?特别是当OP专注于如此微小的表现时,它可能是值得的;可能不会。首先测量,确定它是否值得优化。或者我们全力以赴,使用flex生成适当的lexer。+1错误::-)事实上,这就是他正在做的-转换数字id中的id字符串。如果id来自数据(例如XML),它几乎不能是数字,但决不能是枚举。为什么不简单地使用STL关联数组,那么?如果将成对设置为函数的
静态
成员,则不会在每次输入函数时重新构建。对于如此少的元素,STL关联数组的性能可能会更低。如果我关心性能的话,我会在大约10-20个元素之后开始倾向于STL映射。Th