Search code examples
c++auto

c++ auto variable(map) is assigned garbage value


I tried assigning 'a' variable as follows:

for (auto& a : getMap()[1])

which assigned a garbage value to a. But if I use it after declaring the variable first as shown below, it works normally.

auto vv = getMap()[1];
    for (auto& a : vv)

Why is it a problem if I use it right away without declaring a variable?

#include <string>
#include <map>
#include <memory>
#include <vector>
using namespace std;

typedef struct _mystruct {

} mystruct;

map<int, vector<shared_ptr<mystruct>>> mymap;

void init() {
    vector<shared_ptr<mystruct>> v;
    v.push_back(make_shared<mystruct>(mystruct()));
    mymap[1] = v;
}

map<int, vector<shared_ptr<mystruct>>> getMap() {
    return mymap;
}

int main()
{
    init();

    vector<shared_ptr<mystruct>> v2;
    for (auto& a : getMap()[1]) {
        v2.push_back(a);
    }

    auto vv = getMap()[1];
    for (auto& a : vv) {
        v2.push_back(a);
    }

        return 0;
}

Solution

  • Until C++17 (details that changed since then don't change the answer) the range based for loop was equivalent to (taken from cppreference):

    {    
        auto && __range = range_expression ;
        for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {    
            range_declaration = *__begin;
            loop_statement   
        }    
    }
    

    Because your getMap returns a copy of the map, this:

    auto&& __range = getMap()[1];
    

    Is a reference to an element in the temporary copy of the map that gets destroyed at the end of this statement. __range then holds a dangling reference. As anyhow you probably do not want to copy the whole map just to iterate one of its elements, returning a (const) reference instead of a copy from getMap will fix the issue.

    When you write:

    auto vv = getMap()[1];
    

    Then vv is a copy of the vector from the map. Hence, there is no dangling reference in this case.