Unless you use a custom comparison function object, std::set
uses operator<(const key_type&,key_type&)
by default. Two pointers are equal if, and only if they point to the same object.
Here is an example of three objects:
char a[] = "apple";
char b[] = "apple";
const char (&c)[6] = "apple"
First two are arrays, the third is an lvalue reference that is bound to a string literal object that is also an array. Being separate objects, their address is of course also different. So, if you were to write:
setValues.insert(a)
bool is_in_map = setValues.find("apple") != setValues.end();
The value of is_in_map
would be false
, because the set contains only the address of the string in a
, and not the address of the string in the literal - even though the content of the strings are same.
Solution: Don't use operator<
to compare pointers to c strings. Use std::strcmp
instead. With std::set
, this means using a custom comparison object. However, you aren't done with caveats yet. You must still make sure that the strings stay in memory as long as they are pointed to by the keys in the set. For example, this would be a mistake:
char a[] = "apple";
setValues.insert(a);
return setValues; // oops, we returned setValues outside of the scope
// but it contains a pointer to the string that
// is no longer valid outside of this scope
Solution: Take care of scope, or just use std::string
.
(This answer plagiarises my own answer about std::map
here)