我需要了解以下问题的根源: 我有一些代码必须执行数据的递归遍历。我决定尝试lambda表达式。这是我的代码的完整示例(好吧,这不是我的实际代码,而是具有完全相同流程的存根):
struct Item
{
std::vector<float> values;
};
int main(int argc, char* argv[])
{
std::function<void(uint32_t)> Recursive ;
std::vector<Item> items;
uint32_t sizes[2] = {7,2};
uint32_t counter = 0;
Recursive = [&items,&Recurse,&counter,&sizes](uint32_t c)
{
if (!items.size())
{
items.emplace_back();
}
auto &currItem = items.back();
currItem.values.resize(sizes[c++]);
for (size_t i = 0; i < currItem.values.size(); i++)
{
currItem.values[i]+=5;
if (i == 3)
{
items.emplace_back();
Recursive (c);
printf("end\n");
}
printf("end\n");
}
};
Recursive (counter);
return 0;
}
上面的代码抓取Item
的向量,在第一次调用函数时,它会推送一个Item并对Item::values
向量的成员执行一些操作。当i
索引达到3时,我再次调用Recursive。它再次执行前一个调用已完成的所有操作。但是,在第二个调用返回后,第一个循环终止!这是因为currItem引用不再指向其原始变量,而是指向某个未定义的对象。我想要了解的是:
是否因为lambda的工作方式而发生?但根据this answer,这应该不是我实施中的问题。我的第二个猜测是,一旦lambda进入其递归调用,原始引用就会丢失,并通过调用items.emplace_back();
推送第二个成员。
我不经常使用递归,我之前从未遇到过这种情况。
答案 0 :(得分:3)
这与递归和lambdas无关。
主要问题在于对emplace_back
的调用。如cppreference中所述:
如果new size()大于capacity(),则所有迭代器和引用(包括last-the-end迭代器)都将失效。否则只有过去的迭代器无效。
您的问题的一个解决方案是使用整数索引而不是迭代器。
编辑:不仅迭代器失效,第一个元素(items.begin()
)和过去的元素(items.back()
的返回值)也无效。
您正在使用items.back()
函数获取currItem
变量的值。在第二次调用中emplace_back()
调用后,第一次调用的currItem
变量无效,因此循环无法正确继续。