C++向量将所有元素存储为最后一个元素。

4

我试图将来自XML文件的矩阵数据存储到rawFaceData向量中。当我在第一个for循环中检查cout语句时,对于向量中的所有元素,它都返回我想要的内容。但是当它跳出第一个for循环并进入第二个for循环时,cout始终给我与最后一个元素完全相同的所有元素的值(例如,如果向量大小为4,则cout会4次给我最后一个元素的值!),之前的值都消失了。有谁能告诉我为什么?谢谢!

vector<Mat> rawFaceData;
Mat temp;
FileStorage fsRead = FileStorage();
//output xml datas to a Mat vector for calculation
for(int readCount = 1; readCount < count; readCount++){
    ssfilename.str("");
    ssfilename<<name<<readCount<<postfix;
    filename = ssfilename.str();
    cout<<filename<<endl;
    fsRead.open(filename, FileStorage::READ);
    fsRead["ImageData"]>>temp;
    rawFaceData.push_back(temp);
    cout<<rawFaceData[readCount-1]<<endl;
}
//now raw image datas are now all in the Mat vector, there are count-1 elements in this vector.
//following is avg calculation of the training images.
for(int i = 0; i < rawFaceData.size(); i++){
    cout<<rawFaceData[i]<<"\n"<<endl;
}

文件读取有点混乱,你可以忽略它们。 - user3513507
我认为在你的第一个for循环中,计数器没有得到正确更新,这导致同一元素每次都被push_back到向量中。 - Mantosh Kumar
展示Mat类的定义和实现。听起来它似乎没有适当的值语义。 - Benjamin Lindley
2个回答

4

OpenCV的Mat类使用共享指针和引用计数机制来存储数据,避免不必要的深度复制。

每次从FileStorage中读取数据到temp时,数据会在同一内存位置更新,并且所有对temp数据的引用现在都指向新数据。即旧数据被覆盖。

当您将Mat推入向量中时,数据不会复制到向量元素中。相反,只会向向量添加一个引用,并递增temp的引用计数器。因此,实际上,向量的所有元素都包含相同的数据。

您可能想这样将temp的深层副本push_back到向量中:

rawFaceData.push_back(temp.clone());

2
 Mat temp;

Mat是指针吗?如果是这样,并且您正在向vector中推送指针类型,则在退出第一个for循环后,vector中的所有值都将指向相同的地址,因此您看到的行为就是如此。


我对C++很陌生,所以我在想为什么temp是一个指针,如果我没有声明它呢?因为我使用了Mat temp;而不是Mat* temp; - user3513507
1
@user3513507 这不是一个 Mat 指针。但是 Mat 是一个奇怪的类。一个解决方案可能是在循环内部创建 Mat - juanchopanza
1
@juanchopanza.. Mat类内部使用共享指针存储数据,并使用引用计数。它的复制构造函数和赋值运算符不执行深度复制。它有一个clone成员函数来执行深度复制。 - sgarizvi
1
@sgar91 是的,我知道。我认为这是一个糟糕的设计。不管怎么样,我可能会在循环内部声明 Mat - juanchopanza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接