0

我无法理解在以下情况下如何释放 C++ std::vector 容器

void DoSomething()
{
   cv::Point ** curves;
   int * curve_sizes;
   num_curves = m_curves.size(); //member variable holdings curves
   curves = new cv::Point*[num_curves];
   curve_size = new int[num_curves];

   std::vector<cv::Point> cur_points;
   for(int i = 0; i < num_curves; ++i)
   {
     cur_points = CreatePolyPoints(m_curves[i]);
     curves[i] = &cur_points[0];
     curve_sizes = cur_points.size();
   }

   cv::fillPoly(m_roi, curves, curve_sizes, num_curves, ... );

   //Clear the dynamic data
   // Do i do aything here?   
   delete [] curves;
   delete [] curve_sizes;
}

std::vector<cv::Point> CreatePolyPoints(Curve curve)
{
   std::vector<cv::Point> points;

   //Do work here here
   while(something)
   {
     cv::Point cur_point;
     points.push_back(cur_point);
   }

   return points;
}

提前致谢。如果有人对我的目标感兴趣:在给定由“n”条曲线定义的多边形的情况下生成 ROI。

4

3 回答 3

4

它不是动态分配的,因此一旦超出范围就会被销毁。DoSomething()在您的情况下,您的变量将在函数退出后超出范围。您的局部变量在循环cur_points中获取分配给它的返回值。CreatePolyPoints()发生这种情况时, 的旧内容cur_points将不再存在 - 您无需担心这一点,因为该向量中的Curve对象实例将在每次重新分配向量时被销毁。同样,当cur_points超出范围时。

编辑:你在这里似乎有问题

std::vector<cv::Point> cur_points;
for(int i = 0; i < num_curves; ++i)
{
   cur_points = CreatePolyPoints(m_curves[i]);
   curves[i] = &cur_points[0];    // <-- problem
   curve_sizes = cur_points.size();
}

您在每次迭代时将向量元素 0 的地址分配给您的ith元素curves- 这里的问题是,这将是不再存在的对象的地址。这是因为一旦在循环迭代中下一次被重新分配,向量的内容将不再存在cur_points,因此您存储的指针不指向有效对象 - 它们指向已经被销毁的对象。当你的循环完成时,向量将包含最后一次调用返回的内容CreatePolyPoints。如果您想确保所有cv::Point对象在您调用的点仍然存在,cv::fillPoly您应该考虑通过引用传递向量CreatePolyPoints()函数而不是每次都按值返回一个新向量。这将确保您添加的所有项目CreatePolyPoints在循环完成后仍然存在

于 2012-12-04T20:52:45.433 回答
2

cur_points是一个具有自动存储持续时间的变量。当它被声明时,它就存在了,这里:

std::vector<cv::Point> cur_points;

...并且只要它的封闭范围持续存在,它就会持续存在。

由于这种情况下的“封闭范围”是函数void DoSomething()本身,cur_points因此在函数返回时将超出范围并(自动)销毁。

现在编辑,以上是简单的答案。完整的答案实际上有点复杂,因为还涉及临时人员。

该函数按值CreatePolyPoints返回此vector值。严格遵守此函数的语义和返回值意味着points在该函数中本地创建的对象在CreatePolyPoints返回时将被销毁,并vectorpoints. 该临时值是函数实际返回的值。然后将此临时文件复制到您的cur_points变量中(通过 copy-assignemnt),然后销毁该临时文件。

这是很多浪费的复制,但故事还有更多内容。C++ 标准也有一条规则(称为“AS-IF”规则),它规定编译器可以以它认为合适的任何方式更改您的代码,只要您的程序的行为与编译器的行为相同考虑到副作用,没有做任何更改。

上面的意思是编译器有一个主要的优化机会在许多情况下消除所有这些临时变量,包括这种情况,通过将返回直接复制到cur_points变量而不是通过临时变量。这种最通用形式的优化称为“返回值优化”,大多数(全部?)现代编译器经常这样做。当这种情况发生时(它通常会在这里),行为与我在此处编辑之前所布置的完全一样。

于 2012-12-04T20:55:06.740 回答
0

这是一个不泄漏的 DoSomething 示例,并且已删除错误:

void DoSomething()
{
  std::vector<std::vector<cv::Point>> curves;
  // so long as I do not resize this, or change its length,
  // curves[x].data() will remain valid
  curves.resize( m_curves.size() );

  for(int i = 0; i < num_curves; ++i)
  {
    curves[i] = CreatePolyPoints(m_curves[i]);
  }
  // create buffers of the correct size for the legacy API:
  std::vector<v::Point*> curve_ptrs(curves.size());
  std::vector<int> curve_sizes(curves.size());
  for(int i = 0; i < curves.size(); ++i)
  {
    curve_ptrs[i] = curves[i].data();
    curve_sizes[i] = curves[i].size();
  }

  // call the legacy API:
  cv::fillPoly(m_roi, curve_ptrs.data(), curve_sizes.data(), num_curves, ... );
}
于 2012-12-04T21:29:29.823 回答