Another Question

Discussion in 'C++' started by Amit Gupta, Jan 24, 2007.

  1. Amit Gupta

    Amit Gupta Guest

    I am puzzled, how the hash_map works. In the following declaration, I
    expect it to hash on the character-string, but apparently it hash on
    (maybe) the pointer value of string?

    Any help is greatly appreciated.


    #include <stdio.h>
    #include <map>
    #include <ext/hash_map>

    class A {};

    int main()
    {
    A* a1 = new A();
    A* a2 = new A();

    __gnu_cxx::hash_map<char*, A*> mapper;
    mapper["jan"] = a1;
    mapper["feb"] = a2;

    char* copy = strdup("jan");
    printf("%d\n", mapper[copy]);
    // the following works correctly, as in give the right a1 pointer
    // printf("%d\n", "jan");
    printf("%d\n", mapper["feb"]);

    return (0);
    }
    Amit Gupta, Jan 24, 2007
    #1
    1. Advertising

  2. Amit Gupta

    Amit Gupta Guest

    Ok..I found my mistake. Slightly stupid on my part.

    On Jan 24, 1:08 am, "Amit Gupta" <> wrote:
    > I am puzzled, how the hash_map works. In the following declaration, I
    > expect it to hash on the character-string, but apparently it hash on
    > (maybe) the pointer value of string?
    >
    > Any help is greatly appreciated.
    >
    > #include <stdio.h>
    > #include <map>
    > #include <ext/hash_map>
    >
    > class A {};
    >
    > int main()
    > {
    > A* a1 = new A();
    > A* a2 = new A();
    >
    > __gnu_cxx::hash_map<char*, A*> mapper;
    > mapper["jan"] = a1;
    > mapper["feb"] = a2;
    >
    > char* copy = strdup("jan");
    > printf("%d\n", mapper[copy]);
    > // the following works correctly, as in give the right a1 pointer
    > // printf("%d\n", "jan");
    > printf("%d\n", mapper["feb"]);
    >
    > return (0);
    >
    > }
    Amit Gupta, Jan 24, 2007
    #2
    1. Advertising

  3. Amit Gupta

    Ondra Holub Guest

    Amit Gupta napsal:
    > I am puzzled, how the hash_map works. In the following declaration, I
    > expect it to hash on the character-string, but apparently it hash on
    > (maybe) the pointer value of string?
    >
    > Any help is greatly appreciated.
    >
    >
    > #include <stdio.h>
    > #include <map>
    > #include <ext/hash_map>
    >
    > class A {};
    >
    > int main()
    > {
    > A* a1 = new A();
    > A* a2 = new A();
    >
    > __gnu_cxx::hash_map<char*, A*> mapper;
    > mapper["jan"] = a1;
    > mapper["feb"] = a2;
    >
    > char* copy = strdup("jan");
    > printf("%d\n", mapper[copy]);
    > // the following works correctly, as in give the right a1 pointer
    > // printf("%d\n", "jan");
    > printf("%d\n", mapper["feb"]);
    >
    > return (0);
    > }


    It is not good idea to use const char* (or char*) as key for map
    containers (and I think for hash_map too), because it really uses
    pointers as key value.

    You have no guarantee, that all equal text literals will be merged to
    one place in memory. So on some compilers

    mapper["x"] = 1;
    mapper["x"] = 2;

    Will add 2 different values into mapper, on some will it add value 1
    which is overwritten with value 2.

    Use std::string instead and you do not have problem.
    Ondra Holub, Jan 24, 2007
    #3
  4. Amit Gupta

    Guest

    You have a error in command on #include <ext/hash_map> please tell
    what is it.


    On Jan 24, 4:22 pm, "Ondra Holub" <> wrote:
    > Amit Gupta napsal:
    >
    >
    >
    >
    >
    > > I am puzzled, how the hash_map works. In the following declaration, I
    > > expect it to hash on the character-string, but apparently it hash on
    > > (maybe) the pointer value of string?

    >
    > > Any help is greatly appreciated.

    >
    > > #include <stdio.h>
    > > #include <map>
    > > #include <ext/hash_map>

    >
    > > class A {};

    >
    > > int main()
    > > {
    > > A* a1 = new A();
    > > A* a2 = new A();

    >
    > > __gnu_cxx::hash_map<char*, A*> mapper;
    > > mapper["jan"] = a1;
    > > mapper["feb"] = a2;

    >
    > > char* copy = strdup("jan");
    > > printf("%d\n", mapper[copy]);
    > > // the following works correctly, as in give the right a1 pointer
    > > // printf("%d\n", "jan");
    > > printf("%d\n", mapper["feb"]);

    >
    > > return (0);
    > > }It is not good idea to use const char* (or char*) as key for map

    > containers (and I think for hash_map too), because it really uses
    > pointers as key value.
    >
    > You have no guarantee, that all equal text literals will be merged to
    > one place in memory. So on some compilers
    >
    > mapper["x"] = 1;
    > mapper["x"] = 2;
    >
    > Will add 2 different values into mapper, on some will it add value 1
    > which is overwritten with value 2.
    >
    > Use std::string instead and you do not have problem.- Hide quoted text -- Show quoted text -
    , Jan 24, 2007
    #4
  5. Amit Gupta

    Ondra Holub Guest

    Ondra Holub napsal:
    > Amit Gupta napsal:
    > > I am puzzled, how the hash_map works. In the following declaration, I
    > > expect it to hash on the character-string, but apparently it hash on
    > > (maybe) the pointer value of string?
    > >
    > > Any help is greatly appreciated.
    > >
    > >
    > > #include <stdio.h>
    > > #include <map>
    > > #include <ext/hash_map>
    > >
    > > class A {};
    > >
    > > int main()
    > > {
    > > A* a1 = new A();
    > > A* a2 = new A();
    > >
    > > __gnu_cxx::hash_map<char*, A*> mapper;
    > > mapper["jan"] = a1;
    > > mapper["feb"] = a2;
    > >
    > > char* copy = strdup("jan");
    > > printf("%d\n", mapper[copy]);
    > > // the following works correctly, as in give the right a1 pointer
    > > // printf("%d\n", "jan");
    > > printf("%d\n", mapper["feb"]);
    > >
    > > return (0);
    > > }

    >
    > It is not good idea to use const char* (or char*) as key for map
    > containers (and I think for hash_map too), because it really uses
    > pointers as key value.
    >
    > You have no guarantee, that all equal text literals will be merged to
    > one place in memory. So on some compilers
    >
    > mapper["x"] = 1;
    > mapper["x"] = 2;
    >
    > Will add 2 different values into mapper, on some will it add value 1
    > which is overwritten with value 2.
    >
    > Use std::string instead and you do not have problem.


    If you really need to use const char* as key value, you have to specify
    custom way to compare key values as 3rd parameter:

    struct strCmp
    {
    bool operator()( const char* s1, const char* s2 ) const
    {
    return strcmp(s1, s2) < 0;
    }
    };

    typedef
    std::map<const char*, int, strCmp> M;
    Ondra Holub, Jan 24, 2007
    #5
  6. Amit Gupta

    Ondra Holub Guest

    napsal:
    > You have a error in command on #include <ext/hash_map> please tell
    > what is it.
    >
    >
    > On Jan 24, 4:22 pm, "Ondra Holub" <> wrote:
    > > Amit Gupta napsal:
    > >
    > > > I am puzzled, how the hash_map works. In the following declaration, I
    > > > expect it to hash on the character-string, but apparently it hash on
    > > > (maybe) the pointer value of string?

    > >


    I think your reaction should be on Amit Gupta's message. hash_map is
    not part of standard C++ library. But I thought that the same problem
    may arise with std::map too, so that's why I explained it on std::map.
    You can test it on following code (see line with !!!):

    #include <iostream>
    #include <cstring>
    #include <map>

    struct strCmp
    {
    bool operator()( const char* s1, const char* s2 ) const
    {
    return strcmp(s1, s2) < 0;
    }
    };

    int main()
    {
    typedef
    std::map<const char*, int, strCmp> M1;

    M1 m1;
    m1["a"] = 1;
    m1["a"] = 2;

    for (M1::const_iterator it = m1.begin(); it != m1.end(); ++it)
    std::cout << "m[" << it->first << "] = " << it->second << '\n';

    std::cout << '\n';

    typedef
    std::map<const char*, int> M2;

    M2 m2;
    m2["a"] = 1;
    m2["a"] = 2; //!!! here is undefined, whether it overwrites value 1
    or creates new one

    for (M2::const_iterator it = m2.begin(); it != m2.end(); ++it)
    std::cout << "m[" << it->first << "] = " << it->second << '\n';
    }
    Ondra Holub, Jan 24, 2007
    #6
  7. Amit Gupta

    Default User Guest

    Re: Another Question - TPA

    wrote:

    > You have a error in command on #include <ext/hash_map> please tell
    > what is it.


    Please don't top-post. Your replies belong following or interspersed
    with properly trimmed quotes. See the majority of other posts in the
    newsgroup, or the group FAQ list:
    <http://www.parashift.com/c++-faq-lite/how-to-post.html>
    Default User, Jan 24, 2007
    #7
  8. Amit Gupta

    Amit Gupta Guest

    I agree. The problem here is the comparison functor should be provided
    to the map template (and perhaps hasher too).

    In your example, it is not quite *undefined* what will happen, instead
    it is unpredictable. If both calls to m2["a"] uses same pointer value
    (which it probably will), the data will get over-written.

    Instead, if you do "m2[strdup("a")] = 2;, it will create a new entry.


    > M2 m2;
    > m2["a"] = 1;
    > m2["a"] = 2; //!!! here is undefined, whether it overwrites value 1
    > or creates new one
    >
    > for (M2::const_iterator it = m2.begin(); it != m2.end(); ++it)
    > std::cout << "m[" << it->first << "] = " << it->second << '\n';
    >
    > }
    Amit Gupta, Jan 25, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. nail
    Replies:
    0
    Views:
    1,529
  2. qwerty
    Replies:
    3
    Views:
    9,265
    Scott Allen
    Sep 30, 2004
  3. Maziar Aflatoun
    Replies:
    1
    Views:
    483
    =?Utf-8?B?UGF1bA==?=
    Jan 22, 2005
  4. et
    Replies:
    1
    Views:
    509
    Yunus Emre ALPĂ–ZEN [MCSD.NET]
    Jun 29, 2005
  5. Rob R. Ainscough
    Replies:
    3
    Views:
    312
    Rob R. Ainscough
    Jun 14, 2005
Loading...

Share This Page