C++ unordered_map mit char* als Schlüssel

Ich fühle mich erschöpft, wenn man versucht, die container unordered_map mit char* als Schlüssel (auf Windows, ich benutze VS 2010). Ich weiß, dass ich definieren muss, meine eigene compare-Funktion für char*, die erbt von binary_function. Das folgende ist ein Beispiel-Programm.

#include<unordered_map>
#include <iostream>
#include <string>
using namespace std;

template <class _Tp>  
struct my_equal_to : public binary_function<_Tp, _Tp, bool>  
{  
    bool operator()(const _Tp& __x, const _Tp& __y) const  
    { return strcmp( __x, __y ) == 0; }  
};

typedef unordered_map<char*, unsigned int, ::std::tr1::hash<char*>,  my_equal_to<char*> > my_unordered_map;
//typedef unordered_map<string, unsigned int > my_unordered_map;

my_unordered_map location_map;

int main(){
    char a[10] = "ab";
    location_map.insert(my_unordered_map::value_type(a, 10));
    char b[10] = "abc";
    location_map.insert(my_unordered_map::value_type(b, 20));

    char c[10] = "abc";
    location_map.insert(my_unordered_map::value_type(c, 20));

    printf("map size: %d\n", location_map.size());
    my_unordered_map::iterator it;
    if ((it = location_map.find("abc")) != location_map.end())
    {
        printf("found!\n");
    }

    return 0;
} 

Füge ich den gleichen C-string abc zweimal und nachschlagen. Die zweite Einfügung fehl und es wird nur einen abc im unordered_map. Jedoch, die Ausgabe-Größe ist 3. Es scheint, dass die compare-Funktion funktioniert nicht richtig hier.

Darüber hinaus erhalte ich ein komisches Ergebnis über die find - Funktion, durch die Ausführung des Programms für viele Male, die finden Ergebnis noch ändert! Manchmal wird die Zeichenfolge abc gefunden wird, während die anderen Zeiten abc wird nicht gefunden!!!

Könnte mir jemand helfen zu diesem? Ihre Hilfe ist sehr geschätzt!

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Edit: Nach der Definition einer hash-Funktion für char* durch meine eigenen, das Programm ordnungsgemäß funktioniert. Das volle Programm-code ist unten aufgeführt. Danke an Euch alle.

#include<unordered_map>
#include <iostream>
using namespace std;

template <class _Tp>  
struct my_equal_to : public binary_function<_Tp, _Tp, bool>  
{  
    bool operator()(const _Tp& __x, const _Tp& __y) const  
    { return strcmp( __x, __y ) == 0; }  
};


struct Hash_Func{
    //BKDR hash algorithm
    int operator()(char * str)const
    {
        int seed = 131;//31  131 1313 13131131313 etc//
        int hash = 0;
        while(*str)
        {
            hash = (hash * seed) + (*str);
            str ++;
        }

        return hash & (0x7FFFFFFF);
    }
};

typedef unordered_map<char*, unsigned int, Hash_Func,  my_equal_to<char*> > my_unordered_map;


int main(){
    my_unordered_map location_map;

    char a[10] = "ab";
    location_map.insert(my_unordered_map::value_type(a, 10));
    char b[10] = "abc";
    location_map.insert(my_unordered_map::value_type(b, 20));

    char c[10] = "abc";
    location_map.insert(my_unordered_map::value_type(c, 20));

    printf("map size: %d\n", location_map.size());
    my_unordered_map::iterator it;
    if ((it = location_map.find("abc")) != location_map.end())
    {
        printf("found!\n");
    }

    return 0;
}

Hinweis: die Verwendung char* als Schlüssel-Art für eine unordered_map oder anderen STL-Containern kann gefährlich sein, einen sicheren Weg (scheint die einzige Möglichkeit zu sein) ist: in der main-Funktion new oder malloc einen block (z.B. ein array von c-strings) auf dem heap und füllen Sie es mit c-strings. Legen Sie diese c-strings in unordered_map. Die zugewiesenen Speicherblock freigegeben wird, am Ende der main-Funktion (durch delete oder free).

  • Sie brauchen nicht zu Erben aus binary_function. Es könnte sogar sein, veraltet; ich kann nicht sehen es gerade jetzt.
  • Das ist nicht das problem, aber Namen, die zwei aufeinander folgende Unterstriche (__x, __y) und Namen, die beginnen mit einem Unterstrich gefolgt von einem Großbuchstaben (_Tp) sind reserviert für die Umsetzung (der compiler und seine Bibliothek). Verwenden Sie Sie nicht.
  • Meinst du den den Schlüssel-string zeigte char* verändert werden könnte? Denn das, Was ich denke, ist, dass Sie wollen, der Schlüssel zu konstanter string zeigte const char *. Machen Sie jedes vorkommen char * zu const char * um dies zu unterstützen
  • Gibt es tiefere Fragen, pls nehmen einen Blick auf die Antworten und die Kommentare darunter.
InformationsquelleAutor Bloodmoon | 2013-12-18
Schreibe einen Kommentar