这里有一个共同的编码的图案我要工作有:

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(或类似)来比较键的键比较函数。这样你的地图将按字符串的内容排序,而不是字符串的指针值(即内存中的位置)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top