Answers:
vector<vector<int>>{{77, 777, 7777}}是临时的,然后vector<vector<int>>{{77, 777, 7777}}[0]在range-for中使用将是不确定的行为。
您应该先创建一个变量,例如
#include <iostream>
#include <vector>
using namespace std;
int main()
{
auto v = vector<vector<int>>{{77, 777, 7777}};
for(int i: v[0])
cout << i << ' ';
}
另外,如果您使用Clang 10.0.0,则会发出有关此行为的警告。
警告:支持指针的对象将在完整表达式[-Wdangling-gsl]向量> {{77,777,7777}} [0]的结尾处被破坏。
这是因为要迭代的向量将在进入循环之前被销毁。
通常是这样的:
auto&& range = vector<vector<int>>{{77, 777, 7777}}[0];
auto&& first = std::begin(range);
auto&& last = std::end(range);
for(; first != last; ++first)
{
int i = *first;
// the rest of the loop
}
问题从第一行开始,因为它的评估如下:
首先用给定的参数构造向量的向量,该向量成为临时向量,因为它没有名称。
然后,将范围引用绑定到下标矢量,该矢量仅在包含它的矢量有效的情况下才有效。
到达分号后,临时向量将被销毁,临时向量将在其析构函数中销毁并重新分配所有存储的向量,包括下标的向量。
您最终获得对将要迭代的销毁向量的引用。
为避免此问题,有两种解决方案:
在循环之前声明向量,使其持续到其作用域结束(包括循环)为止。
C ++ 20附带了一个init语句,用于解决这些问题,如果希望立即在循环之后销毁向量,则它比第一种方法要好:
for (vector<vector<int>> vec{{77, 777, 7777}}; int i : vec[0])
{
}
using std::vector代替,using namespace std;以防止这种不良做法传播。