C++中实参和形参结合的方式有三种:传值、引用和传地址。前面两种比较简单,不用多说,这里重点说一下传地址。
传地址一般都跟指针有关,当用指针进行动态存储分配的时候,是需要主动释放内存的,否则会出现内存泄漏。
假设实参是一个进行动态存储分配的指针,那么,一般情况下,释放实参指针或者释放形参指针都可以,因为实参和形参指向的是同一段内存。
对于实参和形参不是指向同一段内存的情况,则实参指针和形参指针都必须得到释放。下面给出来两段程序来说明。
#include<iostream.h>
int sum(int a[3])
{
int s=0;
for(int i=0;i<3;i++)
{
s=s+a[i];
}
//delete []a;
return s;
}
void main()
{
int s=0;
while(1)
{
while(1)
{
int *p;
p=new int[3];
for(int i=0;i<3;i++)
{
p[i]=1;
}
s=sum(p);
delete []p;
break;
}
}
}
IplImage* CReadCameraDlg::strengthImage_Histogram(IplImage *img) //直方图均衡化代码实现
{
IplImage* dst = NULL;
dst = cvCreateImage(cvGetSize(img),img->depth,img->nChannels);
int width = img->width;
int height = img->height;
int step = img->widthStep;
double his[256] = {0};//灰度
double p_hist[256]={0};//灰度比例
double s_hist[256]={0};//累计灰度比例
double total = img->width*img->height;//总像素数
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
his[((uchar*)(img->imageData+i*step))[j]]++;//统计各灰度值的个数
}
for(int i = 0; i < 256; i++)//计算灰度累积概率分布
{
p_hist[i] = (double)his[i]/total;
if(i == 0)s_hist[i] = p_hist[i];
else s_hist[i] = s_hist[i-1]+p_hist[i];
}
//图像增强
for(int i = 0; i < img->height; i++)
{
for(int j = 0; j < img->width; j++)
{
((uchar*)(i * dst->widthStep +dst->imageData))[j] = s_hist[((uchar*)(i * img->widthStep +img->imageData))[j]]*255+0.5;
}
}
cvReleaseImage(&img);//主动释放形参所指向的内存地址。
return dst;
}
//彩色直方图均衡化
IplImage* CReadCameraDlg::EqualizeHistColorImage(IplImage *pImage)//为什么这里的形参指向的内存地址不需要主动释放呢?
//原因在于给它传地址的实参img是由函数cvQueryFrame产生的
//返回值,此时,系统会自动释放。
{
IplImage *pEquaImage=NULL;
pEquaImage = cvCreateImage(cvGetSize(pImage), pImage->depth, 3);//通常IPL图象格式可以存贮非交叉存取的图像,但是cvCreateImage函数只能创建交叉存取图像
// 原图像分成各通道后再均衡化,最后合并即彩色图像的直方图均衡化
const int MAX_CHANNEL = 4;
IplImage *pImageChannel[MAX_CHANNEL] = {NULL};
//IplImage *pImageChannel0[MAX_CHANNEL] = {NULL};//******************
int i;
for (i = 0; i < pImage->nChannels; i++)
pImageChannel[i] = cvCreateImage(cvGetSize(pImage), pImage->depth, 1);
cvSplit(pImage, pImageChannel[0], pImageChannel[1], pImageChannel[2],pImageChannel[3]); //分别复制每个通道到多个单通道图像
for (i = 0; i < pImage->nChannels; i++)
//cvEqualizeHist(pImageChannel[i], pImageChannel[i]);
//pImageChannel0[i]=strengthImage_Histogram(pImageChannel[i]);//*********************
pImageChannel[i]=strengthImage_Histogram(pImageChannel[i]);//pImageChannel[i]首先指向了一段内存地址,作为实参后将该段内存
//地址传递给了形参img,而后,由于函数将返回值赋给了pImageChannel[i],
//所以其右指向了另一段内存地址,而形参img指向的内存地址也需要主动释放。
cvMerge(pImageChannel[0], pImageChannel[1], pImageChannel[2],pImageChannel[3], pEquaImage);
for (i = 0; i < pImage->nChannels; i++)
{
cvReleaseImage(&pImageChannel[i]);
//cvReleaseImage(&pImageChannel0[i]);//***************
}
return pEquaImage;
}
A处代码,由于实参和左边的变量是一样的,导致了实参在传完地址后,实参指针又指向了另一块内存,所以,在这种情况下,实参指针和形参指针都要得到释放。