题
这里有一个共同的编码的图案我要工作有:
class foo {
public:
void InitMap();
void InvokeMethodsInMap();
static void abcMethod();
static void defMethod();
private:
typedef std::map<const char*, pMethod> TMyMap;
TMyMap m_MyMap;
}
void
foo::InitMap()
{
m_MyMap["abc"] = &foo::abcMethod;
m_MyMap["def"] = &foo::defMethod;
}
void
foo::InvokeMethodsInMap()
{
for (TMyMap::const_iterator it = m_MyMap.begin();
it != m_MyMap.end(); it++)
{
(*it->second)(it->first);
}
}
然而,我们发现, 了 该地图是处理(内为循环)可以不同,根据是否建立配置释或者调试。它似乎是编译器优化发生在发布版本影响这一顺序。
我认为,通过使用 begin()
在环路上,增加后的迭代,每个方法的呼吁,它将处理图,以便初始.然而,我还记得读那个线图是实现为哈希表,并以不能得到保证。
这是特别令人讨厌的,因为多数的单元测试运行调试版,并经常奇怪的顺序依赖性的错误没有发现,直到的外部质量保证团队开始测试(因为他们使用的发行版本).
任何人都可以解释的这种奇怪的行为吗?
解决方案
不要使用const char*
作为地图的关键。这意味着地图按字符串的地址排序,而不是字符串的内容。而是使用std::string
作为密钥类型。
std::map
不是哈希表,它通常实现为红黑树,并且保证元素按某些条件排序(默认情况下,<
键之间的比较)。
其他提示
定义的地图是:
地图<Key, Data,="" Compare,="" Alloc="">
这里的最后两个模板中缺省参数:
比较:小<Key>
分配:分配器<value_type>
当插入的新价值观纳入一张地图。新的价值(valueToInsert)是比较古老的价值观,以便(N.B。 这不是顺序搜寻的标准保证了最大插入复杂性O(日志(N))),直到进行比较(价值,ValueToInsert)返回正确的。因为你使用 'const char*' 作为关键。比较目的使用 小<const char*=""> 这类只是做一个 < 在这两个价值观。所以实际上你都比较的指数值(不string)因此顺序是随机(为你不知道从哪里编译器会把串。
有两种可能的解决方案:
- 更改类型的关键因此,它比较串的价值观。
- 定义的另一个比较的类型不会有什么你需要的。
我个人(喜欢克里斯)将只使用一种标准::string因为 < 操作者使用的字符串上返回一个比较的基础上串的内容。但是,辩论为我们就可以定义比较的类型。
struct StringLess
{
bool operator()(const char* const& left,const char* const& right) const
{
return strcmp(left,right) < 0;
}
};
///
typedef std::map<const char*, int,StringLess> TMyMap;
如果要使用const char *作为地图的键,还要设置一个使用strcmp(或类似)来比较键的键比较函数。这样你的地图将按字符串的内容排序,而不是字符串的指针值(即内存中的位置)。