Another Question

A

Amit Gupta

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);
}
 
O

Ondra Holub

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.
 
G

Gayan_on

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


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 -
 
O

Ondra Holub

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;
 
O

Ondra Holub

(e-mail address removed) napsal:
You have a error in command on #include <ext/hash_map> please tell
what is it.

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';
}
 
A

Amit Gupta

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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top