Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL map containing references does not compile

The following:

std::map<int, ClassA &> test;

gives:

error C2101: '&' on constant

While the following

std::map<ClassA &, int> test;

gives

error C2528: '_First' : pointer to reference is illegal

The latter seems like map cannot contain a reference for the key value, since it needs to instantiate the class sometimes and a reference cannot be instantiated without an object. But why does the first case not work?

like image 435
Oliver Zheng Avatar asked May 29 '10 06:05

Oliver Zheng


3 Answers

It is illegal to store references in an stl container, because types must be copy constructible and assignable. References can not be assigned.

Exactly what operation causes the first error is implementation dependent, but I image that it is related to creating a reference and not assigning it immediately. The second error message looks like its actually related to building the map index.

If your type is small, you can copy it into the map, or if it is large consider using pointers instead, but remember that the container will not deallocate the objects for you, you'll have to do that explicitly yourself.

This SO question might be of interest to you.

like image 160
academicRobot Avatar answered Oct 21 '22 06:10

academicRobot


§8.3.2 section 5

There shall be no references to references, no arrays of references, and no pointers to references.

You're probably thinking of references as funny pointers. They are not.

like image 41
fredoverflow Avatar answered Oct 21 '22 06:10

fredoverflow


You cannot store references because they are not copy constructible (and some operations will be impossible because they are not default constructible either).

You can however emulate the behavior using a pointer:

std::map<int, ClassA*> test;

It's a bit annoying because you then need to dereference twice:

std::map<int, ClassA*>::iterator it = test.begin();

it->second->foo();

but with a map it's much less confusing than with a vector or set (it would be (*it)->foo().

Finally, there are some gotchas (those of a pointer):

  • You must ensure than the object pointed to will remain alive as long as you wish to use the pointer
  • The default initialization of a pointer is a random value, using it cause undefined behavior
  • When the pointer is thrown away, the object remains (thankfully), but it does mean you need to make it'll get destroyed at one point
like image 23
Matthieu M. Avatar answered Oct 21 '22 06:10

Matthieu M.