STL push_back:推送动态变化的数组时先前的值被修改
STL push_back: previous values getting modified when pushing a dynamically changing array
我的 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);
但是,我想知道为什么直接使用它不起作用。
你做了一件危险的事情,你推送了一个对象的副本,而不考虑该对象内部的指针或它们指向的内存。您推送的对象具有来自原始对象的按成员分配的数据成员,因此一旦原始对象消失,您的程序就会崩溃。
解决方案是推一个 clone 的对象:
V.push_back(Mat_array_that_gets_updated_in_another_function.clone ());
来自 the OpenCV documentation of Mat
:
Use a copy constructor or assignment operator where there can be an array or expression on the right side (see below). As noted in the introduction, the array assignment is an O(1) operation because it only copies the header and increases the reference counter. The Mat::clone() method can be used to get a full (deep) copy of the array when you need it.
您还可以在文档中看到 Mat
有一个成员 uchar* data
存储矩阵的实际数据条目的位置。
由于您没有对数组进行深度复制,因此对原始数组的更改也会影响您之前放入 vector
中的 "copy",只要它们
没有改变 data
成员指向的地方。
(显然他们没有。)
但是当你做类似 array = Mat::zeros(1,1,CV_32FC1);
的事情时
原来的 Mat
似乎得到了一个新的 data
指针
(或者至少我推断它确实如此,从你说的事实来看
Mat
已经在 vector
未更改)。
我的 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);
但是,我想知道为什么直接使用它不起作用。
你做了一件危险的事情,你推送了一个对象的副本,而不考虑该对象内部的指针或它们指向的内存。您推送的对象具有来自原始对象的按成员分配的数据成员,因此一旦原始对象消失,您的程序就会崩溃。
解决方案是推一个 clone 的对象:
V.push_back(Mat_array_that_gets_updated_in_another_function.clone ());
来自 the OpenCV documentation of Mat
:
Use a copy constructor or assignment operator where there can be an array or expression on the right side (see below). As noted in the introduction, the array assignment is an O(1) operation because it only copies the header and increases the reference counter. The Mat::clone() method can be used to get a full (deep) copy of the array when you need it.
您还可以在文档中看到 Mat
有一个成员 uchar* data
存储矩阵的实际数据条目的位置。
由于您没有对数组进行深度复制,因此对原始数组的更改也会影响您之前放入 vector
中的 "copy",只要它们
没有改变 data
成员指向的地方。
(显然他们没有。)
但是当你做类似 array = Mat::zeros(1,1,CV_32FC1);
的事情时
原来的 Mat
似乎得到了一个新的 data
指针
(或者至少我推断它确实如此,从你说的事实来看
Mat
已经在 vector
未更改)。