问题:
采用 vector::resize 初始化 cv::Mat 的数组, 发现其中所有的cv::Mat对象共享同样的数据
std::vector<cv::Mat> imgs;
imgs.resize(num, cv::Mat::zeros(5, 5, CV_32S));
imgs.assign(num, cv::Mat::zeros(5, 5, CV_32S));
这两种做法都会存在改变数组中一个元素,其余元素也会跟着修改的问题。
原因分析:
1,vector使用值初始化,或resize(当前长度不足时)/assign进行类元素填充时,调用都是拷贝构造函数。
#include <vector>
#include <iostream>
class TestClass
{
public:
TestClass(int a) : a(a)
{
std::cout << "Constructor" << std::endl;
}
TestClass(const TestClass& t)
{
std::cout << "Copy Constructor" << std::endl;
}
int a{ 0 };
};
int main()
{
std::vector<TestClass> vec(3, TestClass(3));
vec.resize(3, TestClass(3));
vec.assign(3, TestClass(3));
/* 这三种初始化方式输出的都是
Constructor
Copy Constructor
Copy Constructor
Copy Constructor
*/
return 0;
}
2,cv::Mat 的拷贝是浅拷贝,创建的新Mat对象与原对象共享同样数据。
解决写法:
1,使用循环, 每个矩阵都被单独分配内存,因此修改一个矩阵不会影响其他矩阵
std::vector<cv::Mat> imgs(num);
for (int i = 0; i < num; ++i)
{
imgs[i] = cv::Mat::zeros(5, 5, CV_32S); // 每个Mat都是独立的
}
2,使用std::fill初始化
std::vector<cv::Mat> imgs(num);
std::fill(imgs.begin(), imgs.end(), cv::Mat::zeros(5, 5, CV_32S));