Why Can't I store references in a `std::map` in C++?
They way I understand it, references are implemented as pointers under the hood. The reason why you can't store them in a map is purely semantic; you have to initialize a reference when it's created and you can't change it afterward anymore. This doesn't mesh with the way a map works.
C++: Is it possible to use a reference as the value in a map?
No. STL container value types need to be assignable. References are not assignable. (You cannot assign them a different object to reference.)
Storing references in a map
std::reference_wrapper
is not default-constructible (otherwise it would be a pointer).
my_map[0]
creates, if 0
is not already a key in the map, a new object of the mapped type, and for this the mapped type needs a default constructor. If your mapped type is not default-constructible, use insert()
:
my_map.insert(std::make_pair(0, std::ref(a)));
or emplace()
:
my_map.emplace(0, std::ref(a));
STL map containing references does not compile
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.
C++ Storing references to values in std::map
The Standard is clear on this in 23.1.2/8
about associative containers
The insert members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.
Passing c++ map by reference and see changes after insert
map
and copyMap
are separate objects and so changing one won't affect other. Moreover, you're returning the map by value from the function passMapByReference
. Instead you could return the map by reference from passMapByReference
as shown below:
#include <iostream>
#include <map>
#include <string>
//------------------------v------->return by reference
std::map<std::string, int>& passMapByReference(std::map<std::string, int>& temp_map){
return temp_map;
}
void printMap(std::map<std::string, int>& temp_map ){
std::cout << temp_map.size() << std::endl;
}
int main()
{
std::map<std::string, int> map;
map["asd"] = 1;
map["dsa"] = 2;
printMap(map);
//copyMap is an lvalue reference to passMapByReference
std::map<std::string, int>& copyMap = passMapByReference(map);
printMap(copyMap);
map["ksdbj"] = 3;
map["askdnijabsd"] = 4;
printMap(map);
printMap(copyMap);//prints 4
}
Working demo
The output of the above program is:
2
2
4
4
Note
I noticed that you have used using namespace std;
and then created a map
with the name map
. This should be avoided as it creates confusion. For example, it becomes hard to see whether the map
you're referring to is a std::map
or the variable named map
. I would recommend using std::
to qualify the standard contianers instead of using using namespace std;
.
Refer to Why is "using namespace std;" considered bad practice?
Reference as key in std::map
C++11
Since C++11 reference wrapper is part of standard.
#include <functional>
std::map<std::reference_wrapper<std::string>, data>
Using Boost
You may want to take a look at boost.ref. It provides a wrapper that enables references to be used in STL-containers like this:
std::map<boost::reference_wrapper<std::string>, data>
Why does storing references (not pointers) in containers in C++ not work?
Containers store objects. References are not objects.
The C++11 specification clearly states (§23.2.1[container.requirements.general]/1):
Containers are objects that store other objects.
Related Topics
Template Function Inside Template Class
How to Safely Average Two Unsigned Ints in C++
How to Add Wtl and Atl to Visual Studio C++ Express 2008
How to Tame the Windows Headers (Useful Defines)
Templates: Template Function Not Playing Well with Class's Template Member Function
C Preprocessor MACro Specialisation Based on an Argument
What Are Customization Point Objects and How to Use Them
How Does =Delete on Destructor Prevent Stack Allocation
How to Use C++ Std::Ostream with Printf-Like Formatting
Why Do Some People Prefer "T Const&" Over "Const T&"
Qt/Qml:Send Qimage from C++ to Qml and Display the Qimage on Gui
Why Do We Use Std::Function in C++ Rather Than the Original C Function Pointer
"Roll-Back" or Undo Any Manipulators Applied to a Stream Without Knowing What the Manipulators Were
In Lambda Functions Syntax, What Purpose Does a 'Capture List' Serve
Why Use ++I Instead of I++ in Cases Where the Value Is Not Used Anywhere Else in the Statement