【opencv】内存自动管理的解释说明

原文

Automatic Memory Management OpenCV handles all the memory automatically.

First of all, std::vector, cv::Mat, and other data structures used by the functions and methods have destructors that deallocate the underlying memory buffers when needed. This means that the destructors do not always deallocate the buffers as in case of Mat. They take into account possible data sharing. A destructor decrements the reference counter associated with the matrix data buffer. The buffer is deallocated if and only if the reference counter reaches zero, that is, when no other structures refer to the same buffer. Similarly, when a Mat instance is copied, no actual data is really copied. Instead, the reference counter is incremented to memorize that there is another owner of the same data. There is also the cv::Mat::clone method that creates a full copy of the matrix data. See the example below:

// create a big 8Mb matrix
Mat A(1000, 1000, CV_64F);
// create another header for the same matrix;
// this is an instant operation, regardless of the matrix size.
Mat B = A;
// create another header for the 3-rd row of A; no data is copied either
Mat C = B.row(3);
// now create a separate copy of the matrix
Mat D = B.clone();
// copy the 5-th row of B to C, that is, copy the 5-th row of A
// to the 3-rd row of A.
B.row(5).copyTo(C);
// now let A and D share the data; after that the modified version
// of A is still referenced by B and C.
A = D;
// now make B an empty matrix (which references no memory buffers),
// but the modified version of A will still be referenced by C,
// despite that C is just a single row of the original A
B.release();
// finally, make a full copy of C. As a result, the big modified
// matrix will be deallocated, since it is not referenced by anyone
C = C.clone();

你看到使用Mat和其他基本数据结构是很简单的。但是对于高层次的类或者是那些在设计时没有考虑到自动内存管理的用户自定义数据类型呢?对于这些情况,OpenCV 提供了 cv::Ptr 模板类,它类似于 C++11 中的 std::shared_ptr。因此,你可以不用普通的指针,而是使用 cv::Ptr

T* ptr = new T(...);

你会看见:

Ptr<T> ptr(new T(...));

或者:

Ptr<T> ptr = makePtr<T>(...);

Ptr<T> 封装了一个指向类型 T 实例的指针以及一个与该指针关联的引用计数。有关详细信息,请参阅 cv::Ptr 的描述。

说明

自动内存管理

在OpenCV中,像std::vectorcv::Mat这样的数据结构,其内部实现会自动管理内存。这意味着当这些对象不再被使用时,它们会自动释放所占用的内存。具体来说,这些数据结构实现了智能引用计数机制。

引用计数机制
  • 共享内存:当一个cv::Mat对象被创建时,它会拥有一个内存缓冲区。如果另一个cv::Mat对象指向同一块内存,那么这块内存的引用计数就会增加。这意味着没有实际的数据复制发生,只有引用计数的增加。

  • 释放内存:当一个cv::Mat对象被销毁时,其内部的析构函数会减少这块内存的引用计数。只有当引用计数降到零时,这块内存才会被释放。

示例代码解释

让我们来看一下给定的代码示例:

  1. Mat A(1000, 1000, CV_64F);

    • 创建了一个大小为1000x1000的双精度浮点数矩阵A
  2. Mat B = A;

    • 创建一个新的Mat对象B,它指向与A相同的内存缓冲区。此时引用计数增加到2。
  3. Mat C = B.row(3);

    • C是一个指向B第三行的新Mat对象。这里C并不是一个完整的矩阵,而是一个视图(view)。
  4. Mat D = B.clone();

    • D是一个B的完整副本。这意味着D拥有自己的内存缓冲区,与AB不共享内存。
  5. B.row(5).copyTo(C);

    • B的第五行复制到C中,即修改了A的第三行。
  6. A = D;

    • 此时A指向了D的内存缓冲区,AD现在共享同一个内存。
  7. B.release();

    • B释放其对内存的引用,引用计数减1。但由于C仍然指向A的一部分,所以内存不会被释放。
  8. C = C.clone();

    • C创建了自己的内存副本,因此原来的内存不再被任何对象引用,最终会被释放。

使用cv::Ptr管理内存

除了基本数据结构之外,对于用户定义的数据类型或高级类,OpenCV提供了cv::Ptr模板类来帮助管理内存。cv::Ptr类似于C++11中的std::shared_ptr,它封装了一个指针和一个引用计数。这样,当最后一个指向某个对象的cv::Ptr实例被销毁时,对象本身也会被自动删除。

例如,可以使用cv::Ptr来替代原始指针:

1Ptr<T> ptr(new T(...));

或者使用makePtr<T>工厂函数:

1Ptr<T> ptr = makePtr<T>(...);

这种方式使得内存管理更加安全且易于维护。

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深耕AI

谢谢鼓励~我将继续创作优质博文

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值