STL Push_back:推送动态变化的数组时修改先前的值

问题描述 投票:0回答:2

我的 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 是否存储数组的当前值而不是已经传递的值:但是一旦调用 push_back() ,元素不应该获取该值并将其保留在内存中,无论如何发生在传入值的变量上吗? V 被定义为 cv::Mat 的向量。

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

c++ arrays vector stl push-back
2个回答
4
投票

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

解决方案是推送对象的克隆

V.push_back(Mat_array_that_gets_updated_in_another_function.clone ());

1
投票

来自

Mat
的 OpenCV 文档:

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

您还可以在文档中看到

Mat
有一个成员
uchar* data
存储矩阵的实际数据条目的位置。

由于您没有对数组进行深层复制,因此对原始数组的更改也会影响您之前放入

vector
中的“副本”,只要它们 没有改变
data
成员指向的位置。 (显然他们没有。) 但是当你做类似
array = Mat::zeros(1,1,CV_32FC1);
的事情时 看起来原来的
Mat
得到了一个新的
data
指针 (或者至少我推断是这样,从你说的事实来看
Mat
已在
vector
中未更改)。

© www.soinside.com 2019 - 2024. All rights reserved.