一、引言

在C++中我们写判断逻辑一般会用if else或switch case语句,比如以下例子:

#include <iostream>using namespace std;class CTest
{
public:enum class ConditionType{TYPE1 = 0,TYPE2,TYPE3,};CTest() = default;~CTest() = default;void execFun(ConditionType eConditionType) //根据条件执行对应函数{switch (eConditionType) {case ConditionType::TYPE1: {func1();break;}case ConditionType::TYPE2: {func2();break;}case ConditionType::TYPE3: {func3();break;}default:break;}}void execAllFun() //执行所有函数{func1();func2();func3();}void func1() { cout << "Func1" << endl; }void func2() { cout << "Func2" << endl; }void func3() { cout << "Func3" << endl; }
};CTest gTest;int main()
{CTest::ConditionType eConditionType = CTest::ConditionType::TYPE1;gTest.execFun(eConditionType);gTest.execAllFun();
}

执行效果如下:

上面的例子很简单,我们用了switch case实现。但有如下不足:

1、swtich语句无法对字符串进行判断,只能对整形/枚举进行判断。

2、代码可读性差。上面的例子因为只有3个判断分支,所以阅读起来还好,但如果有成百上千个判断分支,那execFun函数和execAllFun函数里面的代码会变得非常臃肿,难以阅读。

3、代码可拓展性差。每新增一个分支都要修改execFun函数和execAllFun函数。

二、使用unordered_map查表代替if else和switch case语句

基于上述if else和switch case语句的不足我们可以使用unordered_map查表的方法来重构代码。

#include <iostream>
#include <unordered_map>
#include <functional>using namespace std;class CTest
{
public:enum class ConditionType{TYPE1 = 0,TYPE2,TYPE3,};CTest(){m_map[ConditionType::TYPE1] = bind(&CTest::func1, this);m_map[ConditionType::TYPE2] = bind(&CTest::func2, this);m_map[ConditionType::TYPE3] = bind(&CTest::func3, this);}~CTest() = default;void execFun(ConditionType eConditionType)   //根据条件执行对应函数{auto it = m_map.find(eConditionType);if (it != m_map.end()){it->second();}}void execAllFun() //执行所有函数{for (const auto &e : m_map){e.second();}}void func1() { cout << "Func1" << endl; }void func2() { cout << "Func2" << endl; }void func3() { cout << "Func3" << endl; }
private:unordered_map<ConditionType, function<void()>> m_map;
};CTest gTest;int main()
{CTest::ConditionType eConditionType = CTest::ConditionType::TYPE1;gTest.execFun(eConditionType);gTest.execAllFun();
}

上述代码中使用了std::unordered_map而不是std::map是因为unordered_map查询速度更快,具体可以参考《map和unordered_map的区别》。当然也可以选择其它性能更高的hash表,比如google的swisstable

执行效果如下:

可以看到执行效果跟使用switch case是一摸一样的。并且有如下优点:

1、unordered_map容器类的key可以保存任意类型的数据。所以其实现的判断语句既可以对字符串进行判断,也能对整形/枚举进行判断。

2、代码拓展性强。新增分支不需要修改execFun函数和execAllFun函数,只需要改CTest类的构造函数这一个地方。

3、代码可读性强。直接在CTest类的构造函数中看unordered_map的key 关联了哪个value就可以知道整个判断逻辑。

三、进一步优化:使用单例模式

unordered_map由于建立了哈希表,所以它在最开始建立的时候比较耗时间。在实际的工程项目中我们可以把CTest类设计成单例,让unordered_map只被初始化一次。设计成单例模式的另外一个优点是把要经常使用的资源(全局变量、判断逻辑等)都放到一个地方,这样无论在代码的哪个类里面都能很方便地获取使用这些资源。

#include <iostream>
#include <unordered_map>
#include <functional>using namespace std;template<typename T>
class Singleton
{
public:static T& GetInstance(){static T instance;return instance;}Singleton(T&&) = delete;Singleton(const T&) = delete;void operator= (const T&) = delete;protected:Singleton() = default;virtual ~Singleton() = default;
};#define CT CTest::GetInstance()
class CTest : public Singleton<CTest>
{
public:enum class ConditionType{TYPE1 = 0,TYPE2,TYPE3,};CTest(){m_map[ConditionType::TYPE1] = bind(&CTest::func1, this);m_map[ConditionType::TYPE2] = bind(&CTest::func2, this);m_map[ConditionType::TYPE3] = bind(&CTest::func3, this);}~CTest() = default;void execFun(ConditionType eConditionType) //根据条件执行对应函数{auto it = m_map.find(eConditionType);if (it != m_map.end()){it->second();}}void execAllFun() //执行所有函数{for (const auto &e : m_map){e.second();}}void func1() { cout << "Func1" << endl; }void func2() { cout << "Func2" << endl; }void func3() { cout << "Func3" << endl; }
private:unordered_map<ConditionType, function<void()>> m_map;
};int main()
{CTest::ConditionType eConditionType = CTest::ConditionType::TYPE1;CT.execFun(eConditionType);CT.execAllFun();return 0;
}

执行效果如下:

四、总结

使用unordered_map查表操作代替if else/switch case语句,适用于判断分支非常多的场合。比如我们设计平台服务器,该服务器需要跟数十种不同类型的客户端/设备进行通信,涉及成百上千条通信指令。平台服务器接收通信指令后需要执行对应的回调函数,这个时候我们可以用unordered_map查表代替if else/switch case语句,来提高代码的可读性和维护性。

五、参考

《if-else VS map lookup》

《C++ 单例模式的模板实现》

C++用unordered_map查表代替if else/switch case多判断语句相关推荐

  1. oracle数据库查表_oracle数据库常用的99条查询语句

    1. select * from emp; 2. select empno, ename, job from emp; 3. select empno 编号, ename 姓名, job 工作 fro ...

  2. 21张让你代码能力突飞猛进的速查表(神经网络、机器学习、可视化等)

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:马卡斯·扬,来源:极市平台 作者丨马卡斯·扬@知乎 来源丨http ...

  3. 26 页高清大数据开发代码速查表,提升效率必备!【可下载】

    在各大互联网公司高价抢夺数据人才的环境下,为谋求长期发展.获得高薪,很多人转行到了大数据领域.这条路人才虽缺,但要成为优秀大数据工程师并不轻松:别的不说,光学习新技术,巩固旧知识,就需要耗费大量时间精 ...

  4. 21张让你代码能力突飞猛进的速查表(神经网络、线性代数、可视化等)

    随着深度学习的蓬勃发展,越来越多的小伙伴们开始使用python作为主打代码,python有着种类繁多的第三方库,这里为大家从网络上收集了一些代码速查表,包括深度神经网络.机器学习.数据可视化.pyth ...

  5. 一份火爆国外的PyCharm快捷键和Python代码速查表

    各位小伙伴们,还在为记不住API发愁吗,哈哈哈,最近发现了国外大师整理了一份Python代码速查表和Pycharm快捷键sheet,火爆国外,这里分享给大家. 这个是一份Python代码速查表 下面的 ...

  6. 简述sed、grep和parted的速查表

    下载 sed.grep和parted的速查表来整合新的流程到你的工作中. Linux 因其命令闻名,部分原因是 Linux 执行的几乎所有操作都可以从终端调用:另一部分原因是 Linux 是一个高度模 ...

  7. html 右边是iframe 左右结构_HTML速查表

    HTML速查表 网页标题内容...... Document基本标签(Basic Tags) 最大的标题 . . . . . . . . . . . . 最小的标题 这是一个段落. (换行) (水平线) ...

  8. 数据科学+python+R+数据库+机器学习+(速查表)cheat sheets大全

    数据科学+python+R+数据库+机器学习+(速查表)cheat sheets大全 Learn, compete, hack and get hired! 学习.竞争.精进.996. 东西永远学不完 ...

  9. pandas常用函数说明及速查表

    pandas常用函数说明及速查表 如果你用python做开发,那么几乎肯定会使用pandas库. Pandas 是 Python 语言的一个扩展程序库,用于数据分析. Pandas 是一个开放源码.B ...

最新文章

  1. Gridview改变单元格颜色
  2. 少侠请重新来过 - Vue学习笔记(八) - Vuex
  3. springmvc 实例应用
  4. 【机器学习基础】理解关联规则算法
  5. oneplus 手机kali linux,OnePlus 2(一加2)刷入Kali Nethunter教程
  6. Java main 方法详解
  7. 《虚拟化与云计算》读书感(九)服务器虚拟化的其他核心技术
  8. 数据结构预算法(六) 数组和矩阵(1)
  9. rhel6中dhcp服务器配置文件,如何在CentOS/RHEL 7/6/5配置DHCP服务器
  10. leetcode·双指针
  11. Python 编写几个经典例子
  12. Asp.net教师管理系统
  13. Mysql(3):事务、锁及锁级别
  14. keyberos认证问题导致GSS initiate failed
  15. 什么百度霸屏?百度霸屏是什么意思?
  16. 代码审计之百家cms
  17. linux 下跑通pointnet++网络模型
  18. 李政道和杨振宁合作历程
  19. eclipse字体大小
  20. Flex布局 - 仿携程网移动端首页案列练习

热门文章

  1. 《Adobe Illustrator CC经典教程》—第0课0.15节使用画笔
  2. 利用backtrace和ucontex定位segment错误【转】
  3. photoshop cs之菜单栏功能介绍
  4. 【PaddlePaddle】【论文复现】U-GAT-IT
  5. 集合类 Java中的集合类解析和一些有深入的面试题
  6. 20130723 上海OOW第二日
  7. truffle unbox metacoin出现read ECONNRESET、ETIMEOUT、getaddrinfo ENOENT raw.githubusercontent.com问题
  8. 宇视科技android面试_宇视科技初面
  9. Excel笔记(4)常用函数21-34
  10. C# 学习笔记:委托(5):可变性