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;
}
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.