我无法理解在以下场景中如何释放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。
答案 0 :(得分: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
的{{1}}元素 - 这里的问题是,这将是不再存在的对象的地址。这是因为下次在循环迭代中重新分配curves
时,向量的内容将不再存在,因此您存储的指针不指向有效对象 - 它们指向已经被销毁的对象。循环结束后,向量将包含最后调用cur_points
时返回的内容。如果要确保所有CreatePolyPoints
对象仍然存在于您调用cv::Point
的位置,则应考虑通过引用将该向量传递给cv::fillPoly
函数,而不是返回新的向量每次都有价值。这将确保您在循环结束后仍然存在通过CreatePolyPoints()
添加的所有项目
答案 1 :(得分:2)
cur_points
是具有自动存储持续时间的变量。它在声明时存在,在这里:
std::vector<cv::Point> cur_points;
......只要它的封闭范围仍然存在,它就会持续存在。
由于此情况下的“封闭范围”是函数void DoSomething()
本身,cur_points
将超出范围并在函数返回时被自动销毁。
编辑现在,以上是简单的答案。完整的答案实际上有点复杂,因为临时工也参与其中。
函数CreatePolyPoints
返回此vector
个值。严格遵守此函数的语义和返回值意味着当points
返回时,将在该函数内本地创建的CreatePolyPoints
对象被销毁,并且将构建一个新的临时vector
points
。那个临时实际上是从函数返回的。然后将此临时文件复制到您的cur_points
变量(通过copy-assignemnt),然后销毁临时文件。
这是一个浪费很多的复制,但故事还有一些。 C ++标准还有一条规则(称为“AS-IF”规则),该规则规定编译器可以以其认为合适的任何方式更改代码,只要程序的行为与相同即可。如果编译器没有做任何更改,请考虑副作用。
上述意味着编译器有一个重要的优化机会,可以在很多情况下消除所有这些临时值,包括这种情况,通过将返回直接复制到cur_points
变量而不是通过一个临时的。这种最常见形式的优化被称为“返回值优化”,大多数(所有?)现代编译器经常这样做。当这种情况发生时(通常在这里),行为就像我在编辑之前所描述的那样。
答案 2 :(得分: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, ... );
}