一、表驱动是什么?
表驱动是一种编程模式,是一种将输入变量作为索引在表里查找直接的结果或者处理函数,而不是用很多的逻辑语句来进行判断(比如if-else或者switch-case )。索引表可以是个数组、map或者其他高效率查找的数据结构。
二、表驱动实现方式
下面通过加减乘除来实现一个简易计算器,先用未优化的switch-case来实现:
#include <iostream>
#include <time.h>
int add(int a, int b)
{
return a + b;
}
int subtraction(int a, int b)
{
return a - b;
}
int multiplication(int a, int b)
{
return a * b;
}
int division(int a, int b)
{
assert(b != 0);
return a / b;
}
int Calculator(char symbol, int a, int b)
{
int ans = 0;
switch (symbol)
{
case ' + ':
ans = add(a, b);
break;
case ' - ':
ans = subtraction(a, b);
break;
case ' * ':
ans = multiplication(a, b);
break;
case ' / ':
ans = division(a, b);
break;
default:
std::cout << "wrong symbol" << std::endl;
break;
}
return ans;
}
int main()
{
int res = 0;
clock_t startTimes = clock();
// 一加一减,防止结果溢出
for (int i = 0; i < 1000000; ++i)
{
res = Calculator('+', res, i);
res = Calculator('-', res, i);
}
clock_t endTimes = clock();
std::cout << "switch cost times : " << (endTimes -startTimes)/ CLOCKS_PER_SEC << "ms." << std::endl;
getchar();
return 0;
}
接着,我们使用表驱动方式来做优化:
#include <iostream>
#include <time.h>
#include <map>
int add(int a, int b)
{
return a + b;
}
int subtraction(int a, int b)
{
return a - b;
}
int multiplication(int a, int b)
{
return a * b;
}
int division(int a, int b)
{
assert(b != 0);
return a / b;
}
// 定义函数指针
using func = int (*)(int, int);
int main()
{
int res = 0;
// 这里也可以用map来代替函数指针数组,但是小数据量上实际效果可能还没switch-case快
func table[4];
table['+'] = &add;
table['-'] = &subtraction;
table['*'] = &multiplication;
table['/'] = &division;
clock_t startTimes = clock();
for (int i = 0; i < 1000000; ++i)
{
res = table['+'](res, i);
res = table['-'](res, i);
}
clock_t endTimes = clock();
std::cout << "arrary table cost times : " << (endTimes - startTimes) / CLOCKS_PER_SEC << "ms." << std::endl;
getchar();
return 0;
}
三、测试结果
switch cost times : 7 ms
arrary table cost times : 2 ms
可以看到表驱动模式比switch-case要快很多。
四、总结
表驱动方式代码量少,逻辑清晰,更符合设计模式思想,方便函数增添或者删除。但是在c++里需要用到函数指针、指针数组,对新手不友好。但是如果采用合理的索引表,在数据量较大的情况下可以有效提升程序运行速度。
参考原文链接: