0

在这个来自opencv的例子中,为什么我们不创建一个简单的变量img(而不是一个指针)然后在函数的参数中使用一个简单的指针cvReleaseImage(而在这里,我们将在参数中使用一个双指针,因为我们'重新传递指针的地址:) &img:

IplImage* img = NULL; 
img = cvLoadImage(argv[1], CV_LOAD_IMAGE_UNCHANGED);
cvReleaseImage (&img);

?

此外,当我们在函数中使用简单指针时,我们可以通过在指针上添加另一个*指针来更改指向的值:

例如 :

function random(int* pointer, int* pointer2){
    *pointer = *pointer2 / 2;
}

所以使用双指针,我们应该这样做吗?:

function random(int** doublepointer, int* pointer2){
    **doublepointer = *pointer2 / 2;
}

谢谢你的帮助

4

5 回答 5

2

简单:cvLoadImage()顾名思义,将整个图像加载到内存(考虑一个 10MB 文件)并返回一个IplImage*说明图像数据在内存中的位置。

这非常有用,因为如果它返回一个IplImage而不是,我们的应用程序将需要分配另外 10MB 的内存,复制程序内存中的数据!所以返回一个带有数据内存地址的指针实际上是一个非常聪明的设计决策。

cvReleaseImage()接收一个双指针来反映这种设计。如果您下载 OpenCV v2.3 源代码,您可以在以下位置看到它的实现modules/core/src/array.cpp

2979 CV_IMPL void
2980 cvReleaseImage( IplImage ** image )
2981 {
2982     if( !image )
2983         CV_Error( CV_StsNullPtr, "" );
2984 
2985     if( *image )
2986     {
2987         IplImage* img = *image;
2988         *image = 0;
2989 
2990         cvReleaseData( img );
2991         cvReleaseImageHeader( &img );
2992     }
2993 }

很明显,内存资源的实际释放是由其他 2 个辅助函数完成的,它们在某些时候会调用cvFree()以释放内存。

cvReleaseImage()不过,@Nikolai 共享的简化是正确的。

编辑:回答您的评论。

分配一个指针0永远不会释放malloc()/保留的内存new,它只会使指针指向其他地方,在这种情况下,无处可去!让我们明白什么cvReleaseImage (&img)意思。这一切都始于:

IplImage* img = NULL; 

指针声明与常规变量声明的作用相同:它分配一定数量的内存来存储一些数据。像上面这样的指针声明(在 32 位拱形中)分配 4 个字节的内存来存储其他变量的地址。换句话说,指针本身在它被声明的函数中消耗了 4 个字节的内存。

调用cvReleaseImage(&img)传递指针的地址,而不是它指向的数据的地址(A-HA 时刻就在这里)。

现在,让我们分析剩下的代码:

2985     if( *image ) // does the original pointer points somewhere?
2986     {
             // img copies the address of the data pointed by it's cousing image 
2987         IplImage* img = *image; 
             // and handles the deallocation procedure from now own using img.

             // By clearing the original pointer,
2988         *image = 0; 
             // OpenCV allows us to test for it's release 
             // after cvReleaseImage() executes. 

2989 
2990         cvReleaseData( img );

2991         cvReleaseImageHeader( &img );
2992     }

这样做*image = 0;只是标准程序,所以稍后我们可以检查是否成功释放,如下所示:

cvReleaseImage (&img);
if (img != NULL)
{
  // OOPS! Something went wrong, memory was not released!
} 
于 2012-03-22T13:37:17.520 回答
1

我相信这里的想法是cvReleaseImage()可以做这样的事情:

void cvReleaseImage( IplImage** ppimg ) {
    /* ... */
    free( *ppimg );
    *ppimg = NULL;
}

即释放内存并清理原始指针。

于 2012-03-22T13:24:17.810 回答
1

在“释放”或“自由”函数中非常典型的是将指针传递给指针,以便用户看到的实际指针(在本例中为 img)可以设置为 NULL,因此在被删除后不会意外使用。

是的,您只需双重取消引用即可更改指针指针中的数据,但我建议使用括号:

(*(*doublepointer)) = (*pointer)/2;

我认为它看起来更好。

于 2012-03-22T13:24:39.657 回答
1

至于第一个问题:IplImage 的大小在加载之前可能不知道,而“简单变量”的大小必须在编译时知道。

于 2012-03-22T13:25:12.013 回答
0

函数 cvLoadImage 返回一个指向 IplImage 的指针,因此您不能使用本地定义的 IplImage:

IplImage* cvLoadImage( const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR );

cvReleaseImage 需要指向 IplImage 结构的指针的地址。通过这样做,他们可以在结构被删除时将指针设置为 NULL 值,这样删除的对象就不会被无意中使用。

于 2012-03-22T13:46:49.420 回答