我有一个关于是否在一个被调用的函数中使用'case'或'ifs'的问题。 现在是'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;
}
我的问题是:开关的性能会更好吗?我知道如果使用'ifs',我可以将最有可能的选项放在顶部。
答案 0 :(得分:10)
您不能对字符串使用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;
}
}
答案 1 :(得分:5)
你可以使用gperf
来生成你想要看到的“动词”的完美哈希。然后你可以使用switch
语句。
或者,您可以这样做:
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) { /* ... */ }
老实说,除非选项列表特别大,或者这个功能被称为淫秽次数,否则不值得。
记住:先测量;稍后优化(仅在必要时)。
答案 2 :(得分:4)
您可以将所有值放入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);
}
答案 3 :(得分:2)
你可以很好地使用“enum”来表示这些字符串。然后使用switch case语句。
答案 4 :(得分:2)
我最近遇到的另一种可能或可能不符合您喜欢的替代方案是:
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;
}
答案 5 :(得分:2)
据我所知,有两个问题。优化和if / switch。
首先,代码优化是一个代价高昂的过程。仅优化代码的那些部分,这显然是瓶颈。我怀疑在这种情况下。看起来像是在发送textual-id来决定如何处理消息。消息来自哪里? IPC,XML,文件?你打算怎么处理这条消息?消息内容处理代码的性能如何?代码中应该有一些地方,比字符串比较需要更多的资源。
您是否尝试过一些性能分析器,如Purify,gperf,cachegrind?
关于if / switch:switch是否仅适用于整数类型。 (char,short,int,long,enum)
答案 6 :(得分:2)
假设它确实很重要:
因为strcmp很慢,但是整数比较很快:如果所有命令都是4个字符长 - 恰好适合32位整数 - 你可以将每个字符串转换为32位数字,然后根据它进行切换。
否则,有两种基本方法可以快速将字符串与许多候选字符串进行比较:
或
作为旁注 - 编译器(如MSVC和GCC)已在使用二进制搜索测试交换机条件的交换机上实施了优化。因此,具有256个元素的switch语句将被优化到最多8个比较操作。