做得更好:
class Foo{
std:string option1(MY_ENUM type){
static const std:string f1 = "a";
static const std:string f2 = "b";
static const std:string f3 = "c";
// ...
switch (type) {
case (TYPE_1):{
return f1;
break;
}
case (TYPE_2):{
return f2;
break;
}
// ...
}
}
或者这样做:
class Foo {
private:
const std:string f1 = "a";
const std:string f2 = "b";
const std:string f3 = "c";
public:
std:string option1(MY_ENUM type){
// ...
switch (type){
case (TYPE_1):{
return f1;
break;
}
case (TYPE_2):{
return f2;
break;
}
// ...
}
}
同样,我会做类似的事情将枚举转换为字符串。将字符串保持为函数内的静态const或类中的私有是否更好? - 除了我,没有其他人可以编辑课程。 - 如果类中的任何其他函数知道字符串的值是什么,并且因为它是const,它们无论如何都无法修改它并不重要。
哪个更便宜,并且在运行时和编译期间的开销更少?哪个是更好的做法?
更便宜的是根本不使用std::string
,因为它可能需要运行时初始化,并且还使用查找表从枚举转换为字符串:
const char *enumToStr(MY_ENUM type) {
static const char *const names[] = { "a", "b", "c" };
if (type < sizeof(names) / sizeof(names[0]))
return names[type];
return nullptr;
}
不幸的是,你无法使用这种技巧进行反向转换。此外,假设您的枚举数具有连续的数值,并且在添加或重新排序枚举值时应该小心。
至于“把这些值放到哪里”的问题,只要这个数组是静态的或全局的,从“开销”的角度来看并不重要。我建议将它放在定义这些转换函数的* .cpp文件中的匿名命名空间内的全局变量中,这样它就可以用于这两个函数,但在这个转换单元之外是不可见的:
namespace {
const char *const names[] = ...;
}
c ++中最常见的实现是为此设置一个映射:
#include <iostream>
#include <unordered_map>
#include <string>
enum MY_ENUM {
TYPE_1
, TYPE_2 = 42 // Mind the gap please!
};
const char* const option1(MY_ENUM type) {
static std::unordered_map<MY_ENUM, const char* const> enum2StringMap =
{ { TYPE_1, "a" }
, { TYPE_2, "b" }
// ...
};
if(enum2StringMap.find(type) == enum2StringMap.end()) {
// throw exception or do whatever to indicate an error
return "Invalid enum value";
}
return enum2StringMap[type];
}
反之亦然,您可能需要承担第二张地图的负担,并将其与第一张地图同步:
MY_ENUM option1(const std::string& s) {
static std::unordered_map<std::string, MY_ENUM> string2EnumgMap =
{ { "a" , TYPE_1 }
, { "b" , TYPE_2 }
// ...
};
if(string2EnumgMap.find(s) == string2EnumgMap.end()) {
// throw exception or do whatever to indicate an error
}
return string2EnumgMap[s];
}
使同步更容易的另一个选择(但可能有其他关于性能的缺点)可能是使用qazxsw poi。
boost::bimap
输出:
int main() { std::cout << option1(TYPE_1) << std::endl; std::cout << option1(TYPE_2) << std::endl; std::cout << option1("a") << std::endl; std::cout << option1("b") << std::endl; }
不像a
b
0
42
那样“便宜”,但消除了@r3musn0x proposed solution中提到的问题。
在第一次访问时初始化地图时会有一点开销,但任何愚蠢的搜索都可能被优化为O(log n)与O(n)时间复杂度。
看到一个有效的@KonstantinL's comment。
@ KonstantinL方法的变体;我也认为你可以通过尽可能避免使用online demos来获得最好的服务。但我也想避免地图......
std::string
这使用静态数组而不是地图;连续内存中的线性搜索比使用堆分配节点的树上的二进制搜索更快 - 对于有限数量的值,这似乎就是你的情况。另外 - 这里根本没有使用堆。
笔记: