【问题标题】:if-else VS map lookupif-else VS 地图查找
【发布时间】:2019-11-18 08:26:35
【问题描述】:
std::string v = GetV();
if(v == "AAA") {
    func1();
} else if (v == "BBB" || v == "CCC" || v == "EEE") {
    func2();
} else {
    func3();
}

基本上我想像上面的代码一样进行条件处理。由于将来可能有更多可能的 v 值,我认为 if-else 语句不够好。所以我用map替换它;

enum v_type {
     v_type1,
     v_type2,
     v_type3,
     v_type4
};

string v = GetV();
const static std::map < string, v_type > v_map({
  "AAA",
  v_type1
}, {
  "BBB",
  v_type2
}, {
  "CCC",
  v_type2
});
auto iter = v_map.find(v);
if (iter == v_map.end()) return;
switch
case (iter->second) {
  case v_type1:
    func1();
    break;
  case v_type2:
    func2();
    break;
}

我认为 map(Olog(N)) 甚至 unordered_map 会比 if-else 语句中的字符串比较更快,但权衡可能是内存和 CPU 的映射本身。我对吗?使用 map/unorder_map 是否比 if-else 更好?

【问题讨论】:

  • 为什么不是std::unordered_map&lt;std::string, std::function&lt;void()&gt;?然后,您可以将“键”和要调用的实际函数都放入地图中。有三种方法可以找出映射中的键(countfind 和 C++20 contains),如果它确实直接从映射中“调用”函数(即 @987654331 @ 或者如果你使用find 那么iter-&gt;second())。
  • @Someprogrammerdude 说到性能,我认为只有find 确实是一个不错的选择,因为其他两个会强制执行双重查找......
  • 我们到底在谈论多少个字符串?在超过几十或几百个字符串之前,您可能不会真正注意到差异。无论如何,您可能想先分析您的程序,也许瓶颈在一个完全不同的地方......
  • 考虑您使用的有限标签系列,为这些字符串派生一个完美的散列函数,然后将其用作 SPD 描述的字符串到std::function 的无序映射的散列器,使用find ,然后是生成的非结束迭代器。
  • 正如阿空加瓜所说:不要无缘无故地进行微优化。软件工程师在不必要的地方优化代码是一个很大的陷阱。如果它不是性能瓶颈,请不要修复它。如果您的代码存在性能问题,Forrest 会确定发生的位置,而不是优化您认为有问题的东西。有很好的工具可以分析代码的 CPU 和内存使用情况。

标签: c++ performance data-structures


【解决方案1】:

您可以尝试std::unordered_map&lt;std::string, std::function&lt;void()&gt;&gt;,它将字符串映射到您的函数。 这是一个例子:

#include <iostream>
#include <unordered_map>
#include <functional>

void func1() {std::cout << "Func1" << std::endl;}
void func2() {std::cout << "Func2" << std::endl;}
void func3() {std::cout << "Func3" << std::endl;}

int main()
{
    std::unordered_map<std::string, std::function<void()>> myMap;

    myMap["AAA"] = std::function<void()>(&func1);
    myMap["BBB"] = std::function<void()>(&func2);
    myMap["CCC"] = std::function<void()>(&func2);
    myMap["EEE"] = std::function<void()>(&func2);

    std::string v = GetV();

    if (myMap.find(v) != myMap.end()) {
        myMap.find(v)->second();
    } else {
        func3();
    }

    return 0;
}

你只需要定义哪个字符串对应哪个函数,然后不需要使用switch/case

【讨论】:

  • 映射到函数指针比我的 enum-switch-case 实现要好得多。
猜你喜欢
  • 2012-03-05
  • 1970-01-01
  • 1970-01-01
  • 2014-04-03
  • 1970-01-01
  • 1970-01-01
  • 2013-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多