移动语义和 cv::Mat

Ash*_*Ash 6 c++ opencv computer-vision move-semantics c++11

OpenCV中的文件cv::Mat似乎表明,有在那一刻没有move构造函数,所以像cv::Mat A=std::move(some_other_cv_mat)没有太大的意义。我对这个问题的当前(和天真的)解决方案是从 派生一个类cv::Mat,为此我实现了一个移动构造函数,如下所示:

namespace cv
{
    //matrix object derived from cv::Mat
    class Mvbl_Mat final: public Mat 
    {
        public:
          //constructors
          Mvbl_Mat(){};
          Mvbl_Mat(int rows, int cols, int type, const Scalar   &s):Mat(rows, cols, type, s){}
         //destructor
         ~Mvbl_Mat(){};

          //move constructor
          Mvbl_Mat(Mvbl_Mat && other) noexcept
          {   
              this->data=other.data;
              other.data=nullptr;
           } 
          //move assignment operator
          Mvbl_Mat & operator=(Mvbl_Mat && other)
          {   
              this->data=other.data;
              other.data=nullptr;
              return *this; 
          }   
     };

}
Run Code Online (Sandbox Code Playgroud)

虽然这适用于我目前面临的有限问题,但显然存在许多限制,并且解决方案远非理想。那么,模拟移动语义的最佳方法是cv::Mat什么?

Nat*_*ica 7

没有必要这样做。 cv::Mat的复制构造函数实际上并不复制数据。它基本上是一个引用,所有对象共享相同的数据。

cv::Mat::Mat(const Mat & m)

这是一个重载的成员函数,为了方便而提供。它与上述函数的不同之处仅在于它接受的参数。

参数

m 分配给构造矩阵的数组(作为整体或部分)。这些构造函数不会复制任何数据。相反,指向 m 数据或其子数组的头被构造并与之关联。引用计数器(如果有)递增。因此,当您修改使用此类构造函数形成的矩阵时,您也修改了 m 的相应元素。如果您想拥有子数组的独立副本,请使用 Mat::clone()

  • @NathanOliver 像`shared_ptr` 这样的良好引用计数模型确实支持`move` 语义。如果没有 `move`,你就不能将最后一个引用传递给一个函数,你不得不不必要地保留它(和内存),直到函数返回。 (3认同)
  • @Ash你的意思是移动Mat内容并与源分离?也许这就是您正在寻找的 `cv::Mat source = /*initialization*/ ;` `cv::Mat dest;` `cv::swap(source, dest);` (2认同)

Sdr*_*dra 5

从 4.x OpenCV 开始,提供Mat (Mat &&m)Mat & operator= (Mat &&m).

如果您正在使用 4.x 之前的版本,我建议您查看 中定义的cv::Mat移动构造函数和移动赋值运算符实现modules/core/include/opencv2/core/mat.inl.hpp,因为它比仅复制.data成员要复杂一些。