我正面临一个有趣的情况,并希望与所有人分享。 当然,如果有人能帮助,我将不胜感激!
#include "stdafx.h" #include <map> #define DEF_NAME1 "NAME1" #define DEF_NAME2 "NAME2" #define DEF_NAME3 "NAME3" #define DEF_NAME4 "NAME4" struct TInfo { const char * TName; const char * TArray1[100]; const char * TArray2[100]; }; typedef std::map<const char*, TInfo*> TInfoMap; typedef std::pair<const char*,TInfo*> TInfoPair; static TInfoMap tinfomap; TInfo TInfoArray[] = { {DEF_NAME1,{""}, {""}}, {DEF_NAME2,{""}, {""}}, {DEF_NAME3,{""}, {""}}, {DEF_NAME4,{""}, {""}} }; TInfoMap* GetTInfoMap() { for (int i = 0; i < 3 ; i++ ) tinfomap.insert(TInfoPair(TInfoArray[i].TName,&TInfoArray[i])); return &tinfomap; } int _tmain(int argc, _TCHAR* argv[]) { char *name="NAME3"; TInfo* ptr = new TInfo(); TInfoMap* map1 = GetTInfoMap(); if ( map1->find(name) == map1->end() ) printf("Not found"); else printf("Found!"); return 0; }
我在Windows 2003 Server 64位。 我得到输出“find!” 当我在Release模式下编译/运行这个程序时,当我在Debug模式下编译/运行这个程序时,输出是“Not found”。
任何想法?
问候,
Azher
尝试使用std :: string作为映射中的键。 当你使用char *作为一个键的时候,问题就是如你所期望的那样,比较char *的地址而不是它们的内容。 如果你想使用char *作为一个键,你需要实例化比较谓词和模板的第三个参数。
Debug和Release配置之间的区别可能解释了如何存储const字符串文字 – 是相同的还是单独的存储用于相同的字符串
你并不孤单
编译器不必在相同的内存中分配相同的char约束。 如果你在两个cpp文件中有char约束,地址将会不同。
一个想法是将地图更改为std :: map或用特殊声明比较:
class CompareCString { bool operator()(const char* one,const char* two) { return strcmp(one,two)>0; }; }; typedef std::map<const char*, TInfo*, CompareCString> TInfoMap;
这个比较器比仅仅比较两个指针慢得多。你可以将指针保存在静态约束中。
#define DEFINE_NAME(X) const char * X = #X ; DEFINE_NAME(NAME1) DEFINE_NAME(NAME2) TInfo TInfoArray[] = { {NAME1,{""}, {""}}, {NAME2,{""}, {""}}, };
使用:
map1->find(NAME1); // it should work.
你也可以创建一个const char *的数组,并将cstring的指针改为指向该数组中相同的cstring的指针。 使用set是个好主意:
typedef set<const char *,CompareCString> IternStringSet; const char* iternStringSetData[] = { "Name1","Name2","Name3","Name4" }; enum IternStringNames { Name1,Name2,Name3,Name4 }; IternStringSet iternStringSet(iternStringSetData,iternStringSetData+4); const char* intern(const char* name) { IternStringSet::iterator i = iternStringSet.find(name); return ( i=!iternStringSet.end() ) ? *i : NULL; } const char* intern(IternStringNames name) { return iternStringSetData[name]; }
使用:
const char* what = intern("Name1"); slower ,using strcmp, but done once map1->find( what ); // faster, not using strcmp map1->find( intern(Name1) ); // faster, not using strcmp
我刚刚在我的server2008 64位盒子上试过这个,并且调试和发行打印“Found!”。
所以可能是2003年的某种问题。 我没有2003年的64位,所以不能尝试。