C ++自动变量(地图)被分配垃圾值
c++ auto variable(map) is assigned garbage value
我尝试按如下方式分配 'a' 变量:
for (auto& a : getMap()[1])
它为 a
分配了一个垃圾值。但是,如果我先声明变量后使用它,如下所示,它可以正常工作。
auto vv = getMap()[1];
for (auto& a : vv)
为什么不声明变量就直接使用会出问题?
#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;
}
基于范围的循环是这样的:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
其中 range_expression
在您的代码中是 getMap()[1]
。但问题是 getMap()[1]
一个临时变量,它的生命周期将在 auto && __range = range_expression ;
之后结束。所以range loop一般都会失效。
直到 C++17(从那以后改变的细节不改变答案)基于范围的 for 循环等同于(取自 cppreference):
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
因为你的getMap
returns地图副本,这个:
auto&& __range = getMap()[1];
是对地图临时副本中元素的引用,该副本在此语句结束时被销毁。 __range
然后持有一个悬空引用。无论如何,您可能不想复制整个地图只是为了迭代它的一个元素,返回一个 (const) 引用而不是来自 getMap
的副本将解决这个问题。
当你写:
auto vv = getMap()[1];
那么vv
就是地图上矢量的副本。因此,在这种情况下没有悬挂引用。
我尝试按如下方式分配 'a' 变量:
for (auto& a : getMap()[1])
它为 a
分配了一个垃圾值。但是,如果我先声明变量后使用它,如下所示,它可以正常工作。
auto vv = getMap()[1];
for (auto& a : vv)
为什么不声明变量就直接使用会出问题?
#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;
}
基于范围的循环是这样的:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
其中 range_expression
在您的代码中是 getMap()[1]
。但问题是 getMap()[1]
一个临时变量,它的生命周期将在 auto && __range = range_expression ;
之后结束。所以range loop一般都会失效。
直到 C++17(从那以后改变的细节不改变答案)基于范围的 for 循环等同于(取自 cppreference):
{ auto && __range = range_expression ; for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) { range_declaration = *__begin; loop_statement } }
因为你的getMap
returns地图副本,这个:
auto&& __range = getMap()[1];
是对地图临时副本中元素的引用,该副本在此语句结束时被销毁。 __range
然后持有一个悬空引用。无论如何,您可能不想复制整个地图只是为了迭代它的一个元素,返回一个 (const) 引用而不是来自 getMap
的副本将解决这个问题。
当你写:
auto vv = getMap()[1];
那么vv
就是地图上矢量的副本。因此,在这种情况下没有悬挂引用。