这是向容器添加元素的正确方法吗?

时间:2015-01-09 04:32:34

标签: c++ opencv stl

自从我编写C ++以来已经有一段时间了,所以我想确认一下我是否正确地做了这个:

vector<Mat>
VideoHash::dct3d(vector<Mat> cube)
{
    vector<Mat> dctPlanes;
    for (int k = 0; k < TEMPORAL_DIM; ++k)
    {
        Mat spatial;
        Mat freq;
        cube[k].convertTo(spatial, CV_64F);
        dct(spatial, freq);
        dctPlanes.push_back(freq);
    }

    // Do other stuff here
}

我有一个矩阵向量作为函数的输入。对于向量中的每个矩阵,我转换为不同的数据类型(double),对转换结果执行DCT,然后将DCT的结果存储在另一个向量中。

这看起来是对的吗?我对for循环中创建的矩阵有疑问。循环退出后,它们将超出范围。分配给堆栈中那些矩阵的内存会发生什么变化?循环后是否仍然可以访问该内存(例如,在“在此处执行其他操作”部分)。

2 个答案:

答案 0 :(得分:5)

当你将矩阵推回到向量中时,它会被值复制到由向量分配的内存中。只要存在dctPlanes,其中的矩阵仍然存在。当然,你的临时(空间,频率)将超出每个循环迭代的范围。

编辑:为了解决优化问题,您可以考虑这样的事情:

VideoHash::dct3d(vector<Mat> & cube)
{
    Mat spatial;
    vector<Mat> dctPlanes;
    dctPlanes.resize(TEMPORAL_DIM);
    for (int k = 0; k < TEMPORAL_DIM; ++k)
    {
        cube[k].convertTo(spatial, CV_64F);
        dct(spatial, dctPlanes[k]);
    }

    // Do other stuff here
}

它并不完美,因为理想情况下,当你调整向量大小时,你需要避免调用所有这些构造函数的成本 - 并且有很多方法 - 但与原始代码相比,这将获得不错的收益。

答案 1 :(得分:0)

dctPlanes.push_back(freq)复制临时矩阵freq到容器中。如果Mat具有正确的复制构造函数,您仍然可以通过容器访问数据。显然,freqspatial本身在每次迭代结束时都会被销毁,无法直接访问。

如果关注效率,您可能需要考虑为Mat实现C ++ 11移动构造函数,然后使用:

dctPlanes.push_back( std::move(freq) )

在此行之后,即使在循环范围结束之前,freq本身也会失效 - 因为它已移动到容器中。