C++ Long switch statement or look up with a map?

2019-04-03 07:53发布

In my C++ application, I have some values that act as codes to represent other values. To translate the codes, I've been debating between using a switch statement or an stl map. The switch would look something like this:

int code;
int value;
switch(code)
{
case 1:
    value = 10;
    break;
case 2:
    value = 15;
    break;
}

The map would be an stl::map<int, int> and translation would be a simple lookup with the code used as the key value.

Which one is better/more efficient/cleaner/accepted? Why?

12条回答
SAY GOODBYE
2楼-- · 2019-04-03 08:02

I say map if all you are doing is assigning a value. My reason is that it is extensible without changing code, which your switch statement is not.

btw, how about an enum?

查看更多
走好不送
3楼-- · 2019-04-03 08:02
  • Read the integers into an array/vector
  • sort the array/vector
  • use bsearch on the underlying array
查看更多
我命由我不由天
4楼-- · 2019-04-03 08:03

Normally I'd suggest a map or lookup array or maybe even some hybrid lookup monster (assuming that you're optimizing for speed or code size rather than readability, of course), but it is worth noting that the new versions of GCC are smart enough to replace switch/case assignments like this to lookup tables. While this isn't so great for totally sparse keys it may be if you're keys are in clumps like: 0, 1, 2, 3, 4, 5, 11, 12, 13, 14, 15, 193, 194, 195, 196, 197, 198...

Of course if you could possibly fond some arithmatic to do the conversion, even better (usually). Never overlook shifting, swapping endianness, or more traditional math when doing something like this.

查看更多
你好瞎i
5楼-- · 2019-04-03 08:04

unordered_map probably will be better suited as here as it is using hash table and lookup will be really faster instead of switch.

查看更多
霸刀☆藐视天下
6楼-- · 2019-04-03 08:06

If your codes are contiguous enough and their range permit you would be much better of with old-fashioned straightforward array, something like

int lookup[] = {-1, 10, 15, -1 222};

then the switch statement can be rewritten as simply as

value = lookup[code];

all other options introduce additional cost to some extent.

查看更多
乱世女痞
7楼-- · 2019-04-03 08:13

It rather depends on what the codes are and how many there are. Good compilers have various tricks they use to optimise switch statements, some of which they won't employ with straight if/then statements. Most are bright enough to do simple maths or use lookup/jump tables for case 0, 1, 2 or case 3, 6, 9 for example.

Of course some don't, and many are easily foiled by unusual or irregular sets of values. Also if code for handling several cases looks remarkably similar, cut and paste can lead to maintenance issues. If you have many codes but they can be divided algorithmically into groups, you might consider several/nested switch statements, for example rather than:

switch (code) {
    case 0x0001: ...
    case 0x0002: ...
    ...
    case 0x8001: ...
    case 0x8002: ...
    ...
}

You might use:

if (code & 0x8000) {
    code &= ~0x8000;
    switch (code) {
        case 0x0001: ... // actually 0x8001
        case 0x0002: ... // actually 0x8002
        ...
    }
}
else {
    switch (code) {
        case 0x0001: ...
        case 0x0002: ...
        ...
    }
}

Many language interpreters decode opcodes this way, since a single byte opcode may have additional information packed into various bits, and transcribing all possible combinations and their handlers would be repetitious and fragile. On the other hand, excessive bit mangling can defeat any optimisation by the compiler and be counter-productive.

Unless you're sure this is a real performance bottleneck I'd avoid premature optimisation: do it whichever way strikes you as reasonably robust and quick to implement. As and if your application is running too slowly, profile it and optimise accordingly.

查看更多
登录 后发表回答