c - 双指针以及如何修改函数中的指针

标签 c pointers opencv double-pointer

在这个来自 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;
}

谢谢你的帮助

最佳答案

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

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

cvReleaseImage() 接收一个双指针以反射(reflect)此设计。如果您下载 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() 来释放内存。

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

编辑: 回答您的评论。

将指针分配给 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!
} 

关于c - 双指针以及如何修改函数中的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9823076/

相关文章:

c - 使用 make 将多个 .c 文件链接到一个程序中?

C++ 指向 boolean 值的指针

c - 二叉树 - 指针作为参数

BeagleBone Black 和 Ubuntu 12.04(Precise Pangolin)上的 OpenCV 链接问题

opencv - OpenCV 中的层次聚类

c - 如何使用 libc 正确设置进程优先级限制?

c - for 循环中发生段错误(未执行主体语句)C

python - 在多线程中使用锁

c - 什么是适用于 OSX、Windows XP 或 DOS 的良好 C 编译器?

c - 未使用指针正确交换 2D 矩阵的行 - C