递归Lambdas和本地参考

时间:2018-02-08 15:32:50

标签: c++ recursion c++14

我需要了解以下问题的根源: 我有一些代码必须执行数据的递归遍历。我决定尝试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();推送第二个成员。  我不经常使用递归,我之前从未遇到过这种情况。

1 个答案:

答案 0 :(得分:3)

这与递归和lambdas无关。

主要问题在于对emplace_back的调用。如cppreference中所述:

  

如果new size()大于capacity(),则所有迭代器和引用(包括last-the-end迭代器)都将失效。否则只有过去的迭代器无效。

您的问题的一个解决方案是使用整数索引而不是迭代器。

编辑:不仅迭代器失效,第一个元素(items.begin())和过去的元素(items.back()的返回值)也无效。

您正在使用items.back()函数获取currItem变量的值。在第二次调用中emplace_back()调用后,第一次调用的currItem变量无效,因此循环无法正确继续。