STL push_back:在推动动态变化的数组时,先前的值会被修改

时间:2015-08-19 00:54:30

标签: c++ arrays vector stl push-back

我的CPP代码中的std :: vector.push_back()存在一个非常奇怪的问题。基本上,我所做的只是:

void func()
{
  if(first_time_coming_here)
  {
    do_some_stuff();
    V.push_back(Mat::zeros(3,1,CV_32FC1));  // OpenCV Mat structure
    V.push_back(Mat_array_that_gets_updated_in_another_function);
  }
  else
  {
    do_other_kinds_of_stuff();
    V.push_back(Mat_array_that_gets_updated_in_another_function);   
  }
}

假设在前一个函数中更新的数组最初为[1,1,1],然后第二次执行func(),它已经变为[2,2,2]。我的输出应该是

V = [ [0,0,0], [1,1,1], [2,2,2] ]

但相反,它是

V = [ [0,0,0], [2,2,2], [2,2,2] ]

我真的很难过这里发生了什么。唯一有意义的是,如果V存储数组的CURRENT值而不是已经传递的值:但是一旦调用了push_back(),该元素不应该获取值并将其保留在内存中,无论是什么发生在带来价值的变量? V被定义为cv :: Mat的向量。

编辑:这已通过清除两个函数调用之间的数组值来解决,例如:
    array = Mat :: zeros(1,1,CV_32FC1);
然而,我想知道为什么直接使用它不起作用。

2 个答案:

答案 0 :(得分:4)

你做了一件危险的事情,你推动了一个对象的副本而不尊重该对象内部的指针或它们所指向的内存。您推送的对象具有成员分配的原始数据成员,因此只要原始对象消失,您的程序就会崩溃。

解决方案是改为推送clone对象:

V.push_back(Mat_array_that_gets_updated_in_another_function.clone ());

答案 1 :(得分:1)

来自the OpenCV documentation of Mat

  

使用复制构造函数或赋值运算符,右侧可以有数组或表达式(见下文)。如引言中所述,数组赋值是O(1)操作,因为它只复制标题并增加引用计数器。 Mat :: clone()方法可用于在需要时获取数组的完整(深层)副本。

您还可以在文档中看到Mat有成员uchar* data 其中存储了矩阵的实际数据条目。

由于您没有制作数组的深层副本,因此对原始文件的更改也会影响您之前在vector中添加的“副本” 没有改变data成员指向的位置。 (显然他们没有。) 但当你做array = Mat::zeros(1,1,CV_32FC1);之类的事情时 看来原始的Mat获得了一个新的data指针 (或者至少我推断它确实如此,从你说的那个事实来看 已经Mat中的vector未被更改。