Pointers as keys in map C++ STL

C++PointersMapStl

C++ Problem Overview


I have a question on how pointers to a custom object are handled when used as Keys in an map. More specifically if I define

std::map< CustomClass*, int > foo;

Would the default C++ implementation work to handle these pointers? Or do I need to define a custom comparator function to handle it? In general, is it good practice to use pointers to objects as keys?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

Pointers will be handled but compared as pointers (memory order). You have to pass custom less functor if you wish to compare the objects:

template<class T> struct ptr_less {
    bool operator()(T* lhs, T* rhs) {
        return *lhs < *rhs; }};
map<Object*,int,ptr_less<Object>> mymap;

Solution 3 - C++

C++ standard provided specialisation of std::less for pointers, so yes you can safely use them as map keys etc.

Solution 4 - C++

Leaving aside from the legality of this and any possible semantic misunderstandings, addressed already, I cannot think of any reason to use std::map here rather than std::unordered_map. There are early intercepts of this in Boost and Visual C++ if you are on a pre-C++11 compiler.

Since you appear to be using a pointer to represent a unique object, something like boost::flyweight could be applicable.

Solution 5 - C++

Pointers can be used as keys but especially with a std::map (or std::set) I would not advise it. The behavior of the program is not deterministic i.e. when one iterates over the map the order in which the items in the map are iterated is not guaranteed to be the same. It really depends on the memory address of the object (key). Take a look at this example, as you can see irrespective of the insertion order into the map the items are iterated in a deterministic way when the key is a string rather than a pointer.

http://ideone.com/VKirct

#include <iostream>
#include <map>
using namespace std;

class SomeClass {
	public:
	SomeClass(const std::string& name): m_name(name) {}
	std::string GetName()const {return m_name; }
    bool operator <(const SomeClass& rhs) const { return m_name < rhs.m_name; }
	private:
	std::string m_name;
};

auto print_seq  = [](const auto& seq) { for (const auto& itr: seq) {std::cout << itr.second << " , ";} std::cout << std::endl;};

int main() {
	// your code goes here
	std::map<SomeClass*, std::string> pointer_keyed_map;
	SomeClass s3("object3");
	SomeClass s1("object1");
	SomeClass s2("object2");
	pointer_keyed_map.insert(std::make_pair(&s1, s1.GetName()));
	pointer_keyed_map.insert(std::make_pair(&s2, s2.GetName()));
	pointer_keyed_map.insert(std::make_pair(&s3, s3.GetName()));
	std::cout << "Pointer based keys: object order" << std::endl;
	print_seq(pointer_keyed_map);

	std::map<SomeClass, std::string> int_keyed_map;
	int_keyed_map.insert(std::make_pair(s3, s3.GetName()));
	int_keyed_map.insert(std::make_pair(s1, s1.GetName()));
	int_keyed_map.insert(std::make_pair(s2, s2.GetName()));
	std::cout << "String based keys: object order" << std::endl;
	print_seq(int_keyed_map);
	return 0;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmmar HusainView Question on Stackoverflow
Solution 1 - C++Neil KirkView Answer on Stackoverflow
Solution 2 - C++firdaView Answer on Stackoverflow
Solution 3 - C++Wojtek SurowkaView Answer on Stackoverflow
Solution 4 - C++Steve TownsendView Answer on Stackoverflow
Solution 5 - C++Chenna VView Answer on Stackoverflow