C++ map, use const reference as value type, what is the problem here?

Today I saw my boss's code which uses a const reference as a map's value type.

Here's the code:

class ConfigManager{
    public:
        map<PB::Point, const PB::WorldPoint&, compare_point> world_point;
    //the rest are omitted
};

(PB is Google Protobuf, we are using the Protobuf library. I don't know much about it or if it's relevant to the question. )

What this class does is that it reads some config files and put it into some maps for search.


At first I was surprised because I haven't seen a map with a reference as its value, which is e.g. map<int, classA&> aMap.

So then I searched on SO and these 2 questions tell me that I can't do that.

C++: Is it possible to use a reference as the value in a map?

STL map containing references does not compile

Then I tried this code, indeed it doesn't compile:

Code Example1

struct A {
    int x = 3;
    int y = 4;
};

map<int, A&> myMap;

int main() {
    A a;
    myMap.insert(make_pair(1, a));
}

But if I change map<int, A&> myMap; to map<int, const A&> myMap;, it compiles.

Yet another problem occured. With map<int, const A&> myMap;, I can't use [] to get the pair, but I can use map.find().

(My boss told me to use map.find() after I told him using[] can't compile).

Code Example2

struct A {
    int x = 3;
    int y = 4;
};

map<int, const A&> myMap;

int main() {
    A a;
    myMap.insert(make_pair(1, a));

    //can't compile
    cout << myMap[1].x << " " << myMap[1].y << endl; 
    
    //can work
    //auto it = myMap.find(1);
    //cout << it->second.x << " " << it->second.y << endl;
}

So till here I was thinking my boss was correct. His code was correct.


The last story is that I showed the code to some online friends. And they noticed a problem.

Code Example3

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

struct A {
    int x = 3;
    int y = 4;
    ~A(){
        cout << "~A():" << x << endl;
        x = 0;
        y = 0;
    }
};

map<string, const A&> myMap;

int main() {
    A a;
    cout << a.x << " " << a.y << endl;
    myMap.insert(make_pair("love", a));
    a.x = 999;
    cout << "hello" << endl;
    auto s = myMap.find("love");
    cout << s->second.x << " " << s->second.y << endl;
}

The output is:

3 4
~A():3
hello
0 0
~A():999

If I understand the output correctly(correct me if I get it wrong), it indicates that:

  1. make_pair("love", a) creates an object pair<"love, temproray copy of a>. And the pair gets inserted into myMap.
  2. Somehow, I don't know how it happens, the temporary copy of a gets destructed immediately. To me, it means the memory of the temporary copy of a is now not owned by anyone and it is now a free space of memory can be filled with any values, if I understand correctly.

So now I am getting confused again.

My questions are:

  1. What happen to the Code Example3? Is my understanding correct? Why does temporary copy of a get destructed right after the statement? Isn't using a const reference can extend a temporary's lifetime? I mean, I think the it should not get destructed till main finishes.

  2. Is my boss's code correct? In another word, can I use const reference as a map's value type? According to Code Example3, the usage seems to be wrong. So I wonder if there other cases?



Read more here: https://stackoverflow.com/questions/64482960/c-map-use-const-reference-as-value-type-what-is-the-problem-here

Content Attribution

This content was originally published by Rick at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: