我有一个这样的课程:
class MyClass
{
cv::Mat image;
public:
init()
{
image=imread("test.jpg");
}
cv::Mat getImage()
{
return image;
}
void reset()
{
// what should I write here?
}
}
cv::Mat myImage;
void main()
{
MyClass myclass;
myclass.init();
myImage=myclass.getImage();
// do something with image;
myclass.reset();
// at this point the memory allocated by myclass.image should be released and also myImage should be invalidated (be an empty image).
}
注意:我知道我可以使myImage成为局部变量并解决问题,但我想知道如何释放cv :: Mat分配的内存,即使引用计数不为零。
image.release()不要释放内存,因为有一个图像副本(myImage),我需要确保即使有图像副本也会释放内存。
对于那些可能会抱怨使myImage无效的人,类规范说当调用reset时,由类创建的所有图像都变得无效,如果用户需要图像,他们需要在调用类重置之前克隆它。
deallocate不起作用,也不会释放内存。
答案 0 :(得分:2)
这段代码怎么样?
这应该停用引用计数。
我没有尝试过,但我想它应该有用(我希望这个想法很明确)。但是,如果还有其他Mat引用仍在使用中,您显然会遇到访问错误!
class MyClass
{
cv::Mat image;
unsigned char * imageData; // TODO: set to zero in constructor!
public:
init()
{
cv::Mat tmp = imread("test.jpg");
// TODO: test if non-zero and release before allocating new memory
imageData = (unsigned char*) malloc(tmp.cols*tmp.rows*3*sizeof(unsigned char)); // allocate memory for your image
// TODO: maybe it is possible to get the size of "tmp"'s data directly, which would be much better because of widthStep things, etc. The formula "tmp.cols*tmp.rows*3*sizeof(unsigned char)" might not be correct for all kind of input images!
// create Mat header that uses present memory
image=cv::Mat(tmp.rows, tmp.cols, 3, imageData );
// copy loaded image to allocated memory:
tmp.copyTo(image); // here you must be sure that "image" is big enough to hold "tmp"'s data. Otherwise a new Mat will be created.
// tmp will be cleared automatically
}
cv::Mat getImage()
{
return image;
}
void reset()
{
image = cv::Mat();
free(imageData);
}
}
答案 1 :(得分:0)
也许真正的问题是这个设计是否有意义。该类用户在调用Mat
时保留以前收到的reset
对象副本的唯一原因是他们仍然希望对其进行操作。保留该对象没有其他理由。因此,在调用reset
时使此副本无效必然会导致崩溃。因此,这种行为毫无意义。此外,它引入了一个隐含的约束,用户必须知道并且不通过类的接口进行通信。这不是一个好的设计。
相反,内存使用的责任在于类用户。他们知道如果他们在保留所有图像的同时调用getImage
和reset
一百次,他们将消耗大量内存。这是他们的决定,而不是你班级的决定。
相反,在类中创建新的Mat
对象时,您应该确保处理内存不足时的情况,因此如果无法创建新图像,则可以正确处理和通信。毕竟你永远不知道你的图像是否有足够的内存,即使你每次都发布旧图像。
答案 2 :(得分:-1)
getImage必须返回参考Mat&和重置功能中的image.release()将完成这项工作。