c++ - cv::Mat 类是否存在设计缺陷?

标签 c++ oop opencv resources

我经常使用 OpenCV C++ 接口(interface)并设计了许多使用 Mat 作为私有(private)资源的类。

最近,我开始关注 Mat 类,因为它总是使用图像数据作为共享资源,除非我明确调用 clone。 即使我写了 const Mat,我也不能确定图像数据以后不会从外部更改。

所以我需要克隆以确保封装。但是需要显式克隆一个 Mat 的问题是它通常是不必要且昂贵的。另一方面,我知道对共享图像数据的需求源于 roi 选择器,并且能够编写如下内容: Mat m_small = m_big(my_roi).

我的问题是:

1.) 不应该懒惰地克隆 cv::Mat 类吗? 这样用户就不会从外部将 Mat 视为共享资源处理程序。当需要真正的共享图像数据时,用户不应该显式实例化一个名为 SharedMat 的类吗?
2.) 在将 cv::Mat 作为类的私有(private)资源的情况下,您是否有任何比总是克隆更好的策略


UPDATE:“除非您打算修改数据,否则不要使用 Mat::clone()。” (瓦迪姆·皮萨列夫斯基)
这个想法有问题。 考虑一下你有这个类的情况:

class Res_handler{
public:
  const Mat emit_mat(){ return m_treasure; } // I argue you are compelled to clone here.
private:
  Mat m_treasure;
};

如果你不clone在这种情况下你可以写

Mat m_pirate = res_handler.emit_mat(); m_pirate = Scalar(0,0,0);

通过 m_piratem_treasure< 之间共享的图像数据导致 res_handler 内的 m_treasure 完全停电。 :) 所以为了避免意外修改内部m_treasure你需要clone

另一方面,这个解决方案也有缺陷:

const Mat m_pirate = res_handler.emit_mat(); 

因为m_treasure也可以被修改,所以m_pirate的内容在后台被修改了,让盗版的程序员很头疼。 :)

最佳答案

是的,这是一个糟糕的设计。因为Mat内部实现共享所有权,不兼容选择所有权策略的标准方式,即智能指针。基本问题是数据和所有权是正交的,应该分开。

因为它是可变的,即使是 const Mat更像是 const shared_ptr<Mat> , 无法描述包含的 Mat应该是可变的,即 shared_ptr<const Mat> .这与 final 的问题非常相似。在 Java 中,如果你熟悉的话。

我相信您可以通过包装 Mat 来避开这些问题在与 Mat 公开相同接口(interface)的类中,但它在默认共享实现之上实现了写时复制行为。

关于c++ - cv::Mat 类是否存在设计缺陷?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13713625/

相关文章:

c++ - 锁定多个互斥锁

c++ - 可以将静态 constexpr 变量用作模板参数吗

使用 range() 的 PHP 类属性

c++ - CV_RETR_LIST、CV_RETR_TREE、CV_RETR_EXTERNAL 之间的区别?

python - 矩形没有出现在 opencv 中

c++ - C2248 - 将 QScopedPointer 传递给函数时无法访问私有(private)成员

c++ - 模板方法和默认模板参数

java - java中的多个接口(interface)具有相同的方法名称和变量名称

php oop数据库查询

python - OpenCV Python对光线变化的文档照片的最佳阈值