Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C string map key

Tags:

c++

map

cstring

Is there any issue with using a C string as a map key?

std::map<const char*, int> imap;

The order of the elements in the map doesn't matter, so it's okay if they are ordered using std::less<const char*>.

I'm using Visual Studio and according to MSDN (Microsoft specific):

In some cases, identical string literals can be "pooled" to save space in the executable file. In string-literal pooling, the compiler causes all references to a particular string literal to point to the same location in memory, instead of having each reference point to a separate instance of the string literal.

It says that they are only pooled in some cases, so it seems like accessing the map elements using a string literal would be a bad idea:

//Could these be referring to different map elements?
int i = imap["hello"];
int j = imap["hello"];

Is it possible to overload operator== for const char* so that the actual C string and not the pointer values would be used to determine if the map elements are equal:

bool operator==(const char* a, const char* b)
{
    return strcmp(a, b) == 0 ? true : false;
}

Is it ever a good idea to use a C string as a map key?

like image 794
user974967 Avatar asked Dec 13 '12 11:12

user974967


2 Answers

Is it possible to overload operator== for const char* so that the actual C string and not the pointer values would be used to determine if the map elements are equal

No it's not, and yes, it's not a good idea for exactly the reason pointed out in the question and because you don't need char*, you can use a std::string instead. (you can provide a custom compare function - as pointed out by simonc, but I'd advise against it)

//Could these be referring to different map elements?
int i = imap["hello"];
int j = imap["hello"];

Yes, and they can even refer to elements that don't exist yet, but they'll be created by operator[] and be value initialized. The same issue exists with assignment:

imap["hello"] = 0;
imap["hello"] = 1;

The map could now have 1 or 2 elements.

like image 129
Luchian Grigore Avatar answered Sep 17 '22 14:09

Luchian Grigore


You can provide a map with a custom comparitor which compares the C strings

std::map<const char*,YourType,CstrCmp>;

bool CstrCmp::operator()(const char* a, const char* b) const
{
    return strcmp(a, b) < 0;
}
like image 35
simonc Avatar answered Sep 19 '22 14:09

simonc