首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果std::vector是按值返回的,那么它什么时候被释放?

如果std::vector是按值返回的,那么它什么时候被释放?
EN

Stack Overflow用户
提问于 2012-12-05 04:50:41
回答 3查看 230关注 0票数 0

我很难理解在下面的场景中如何释放C++ std::vector容器

代码语言:javascript
复制
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。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-12-05 04:52:45

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

编辑:您似乎在这里遇到了问题

代码语言:javascript
复制
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的地址分配给curvesith元素-这里的问题是,这将是一个不再存在的对象的地址。这是因为一旦下一次在循环迭代中重新分配cur_points,向量的内容将不再存在,因此您存储的指针并不指向有效的对象-它们指向已经被销毁的对象。当您的循环结束时,向量将包含最后一次对CreatePolyPoints调用中返回的内容。如果希望确保所有cv::Point对象在调用cv::fillPoly时仍然存在,则应该考虑通过引用CreatePolyPoints()函数来传递向量,而不是每次都通过值返回一个新的向量。这将确保您通过CreatePolyPoints添加的所有项目在循环完成后仍将存在

票数 4
EN

Stack Overflow用户

发布于 2012-12-05 04:55:07

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

代码语言:javascript
复制
std::vector<cv::Point> cur_points;

只要...and的封闭作用域仍然存在,它就会一直存在。

由于本例中的“封闭作用域”是函数void DoSomething()本身,因此当函数返回时,cur_points将超出作用域并被(自动)销毁。

现在编辑,上面就是简单的答案。完整的答案实际上有点复杂,因为还涉及到时间因素。

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

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

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

票数 2
EN

Stack Overflow用户

发布于 2012-12-05 05:29:30

下面是一个不泄漏的DoSomething示例,并删除了错误:

代码语言:javascript
复制
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, ... );
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13711672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档