我很难理解在下面的场景中如何释放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。
发布于 2012-12-05 04:52:45
它不是动态分配的,因此一旦超出范围就会被销毁。在本例中,在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的地址分配给curves的ith元素-这里的问题是,这将是一个不再存在的对象的地址。这是因为一旦下一次在循环迭代中重新分配cur_points,向量的内容将不再存在,因此您存储的指针并不指向有效的对象-它们指向已经被销毁的对象。当您的循环结束时,向量将包含最后一次对CreatePolyPoints的调用中返回的内容。如果希望确保所有cv::Point对象在调用cv::fillPoly时仍然存在,则应该考虑通过引用CreatePolyPoints()函数来传递向量,而不是每次都通过值返回一个新的向量。这将确保您通过CreatePolyPoints添加的所有项目在循环完成后仍将存在
发布于 2012-12-05 04:55:07
cur_points是一个具有自动存储持续时间的变量。当它被声明时,它就会存在,在这里:
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变量,而不是通过临时。这种优化以其最一般的形式被称为“返回值优化”,并且最(全部?)现代编译器经常这样做。当这种情况发生时(通常在这里会发生),行为与我在编辑之前所展示的完全一样。
发布于 2012-12-05 05:29:30
下面是一个不泄漏的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, ... );
}https://stackoverflow.com/questions/13711672
复制相似问题