Pointers as Keys in Map C++ Stl

Pointers as keys in map C++ STL

The default implementation will compare the addresses stored by the pointers, so different objects will be considered as different keys. However, the logical state of the object will not be considered. For example, if you use std::string * as the key, two different std::string objects with the same text of "Hello" would be considered a different key! (When stored in the map by their addresses)

It's ok to use pointers as keys so long as you understand the important difference above.

std::map, pointer to map key value, is this possible?

First, maps are guaranteed to be stable; i.e. the iterators are not invalidated by element insertion or deletion (except the element being deleted of course).

However, stability of iterator does not guarantee stability of pointers! Although it usually happens that most implementations use pointers - at least at some level - to implement iterators (which means it is quite safe to assume your solution will work), what you should really store is the iterator itself.

What you could do is create a small object like:

struct StringPtrInMap
{
typedef std::map<string,string>::iterator iterator;
StringPtrInMap(iterator i) : it(i) {}
const string& operator*() const { return it->first; }
const string* operator->() const { return &it->first; }
iterator it;
}

And then store that instead of a string pointer.

C++ map with pointer as key. Memory management

If you use smart pointer as a key in a std::map without custom comparator, then it does not work, as you simply would not replace one object with another, as pointer to one object is not equivalent to another and replace would not occur. If you do use comparator then it still would not work automatically, as key is a constant and only value modified when you replace item in a map. So I think you have 3 ways to fix your issue (assuming you do use custom comparator):

  1. Still use std::map but when replacing element remove previous key/value pair first and insert new pair, do not use operator[] or assignment to iterator->second
  2. Still use std::map but keep smart pointer and data in value part and copy key from your object.
  3. Use different container, for example Boost.Multi-index. You may not need multiple indexes but this container allows using part of object as a key and replace method.

Issue with C++ map using member function pointers as keys

The error is telling you all you need to know:

invalid operands of types ‘int (MyClass::* const)()’ and ‘int (MyClass::* const)()’ to binary ‘operator<’

You cannot compare member function pointers using standard operator<, so you must provide a custom comparator when declaring your map.

Unfortunately, pointers to member functions cannot be compared for inequality, so you cannot define a comparison operator or use a std::mapin this case. I suggest using std::unordered_map, which only needs a std::hash and equality comparison, which you can do. See here for hashing and here for equality comparison.

Hashing pointers as Keys for unordered_map in C++ STL

std::hash<T*> is defined but the details of how it operates are implementation dependent. It will certainly be safe to use, and I'd consider it good practice - as long as it's the pointer you need as the key, and not the object contents itself.

Can I have a C++ map where multiple keys reference the value without using pointers?

No, you will need to use pointers for this. Each entry in the map maintains a copy of the value assigned, which means that you cannot have two keys referring to the same element. Now if you store pointers to the element, then two keys will refer to two separate pointers that will refer to the exact same in memory element.

For some implementation details, std::map is implemented as a balanced tree where in each node contains a std::pair<const Key,Value> object (and extra information for the tree structure). When you do m[ key ] the node containing the key is looked up or a new node is created in the tree and the reference to the Value subobject of the pair is returned.

how to store pointers in map

I've typedef'd this stuff to make it more readable...

typedef std::map<std::string, MyObj*> MyMap;
typedef std::pair<std::string, MyObj*> MyPair;

MyMap myMap;
string strFilename = "MyFile";
MyObj* pObj = new MyObj();
myMap.insert(MyPair(strFilename, pObj));

Using a STL map of function pointers

Whatever your function signatures are:

typedef void (*ScriptFunction)(void); // function pointer type
typedef std::unordered_map<std::string, ScriptFunction> script_map;

// ...

void some_function()
{
}

// ...

script_map m;
m.emplace("blah", &some_function);

// ...

void call_script(const std::string& pFunction)
{
auto iter = m.find(pFunction);
if (iter == m.end())
{
// not found
}

(*iter->second)();
}

Note that the ScriptFunction type could be generalized to std::function</* whatever*/> so you can support any callable thing, not just exactly function pointers.

value_type for a map having pointers as key

Your reasoning is correct, value_type::first would be char const * const.

There is a common source of confusion in thinking that const T when T is a type * is const type *, but that is not so. Unlike macros, typedefs are not text substitution, nor are template arguments. When you do const T, if T is a typedef or template argument, you are adding a const to the type as a whole.

That is the one reason why I like to write my consts at the right of the type, as it causes less confusion: T const *, add an extra const, get T const * const.



Related Topics



Leave a reply



Submit