当前位置:编程学习 > C/C++ >>

使用动态数组结构的一个好处

作者:朱金灿 

  请注意,这里我所说的动态数组不是指你自己new 出来的数组,而是指STL 中的std::vector 和MFC 中的CArray 之类的容器。开始以为使用std::vector 不过是免除动态内存之苦。免除自己手动开辟和释放内存是一方面,实际上在使用的过程中你会逐渐发现使用std::vector 的好处。今天我就发现了一个好处。

 

今天我修改别人写的一个图像匹配算法,所谓图像匹配就是找出两幅图像中相同的地方,在我这个算法中就是找出匹配结果点。别人的代码大致是这样的:

 


view plaincopy to clipboardprint?
/*! 
 rief 匹配点信息结构体 
     
*/ 
struct PointInfo   
{  
    long x;  
    long y;  
    long Geo_x;  
    long Geo_y;  
    PointInfo()  
    {  
        x= 0;  
        y=0;  
        Geo_x = 0;  
        Geo_y = 0;  
    }  
};  
/*! 
rief 匹配两幅图像,返回匹配结果点数组 
param pLeftImg  左图像文件句柄 
param pRightImg 右图像文将句柄 
param lVaildNum 返回的匹配结果点个数 
eturn 匹配结果点数组 
*/ 
PointInfo* ImageMatch(FILE* pLeftImg,FILE* pRightImg,long &lVaildNum)  
{  
      
     long Imgwidth = 0;  
     long ImgHeight= 0;  
     // 获取左图像宽高,具体代码不写  
      
     // 开辟一个整幅图像大小的数组  
     PointInfo* pResultPt  = new  PointInfo[Imgwidth*ImgHeight];  
   
     // 开始图像匹配,具体代码不写  
       
     return pResultPt;  

/*!
 rief 匹配点信息结构体
   
*/
struct PointInfo
{
 long x;
 long y;
 long Geo_x;
 long Geo_y;
 PointInfo()
 {
  x= 0;
  y=0;
        Geo_x = 0;
        Geo_y = 0;
 }
};
/*!
rief 匹配两幅图像,返回匹配结果点数组
param pLeftImg  左图像文件句柄
param pRightImg 右图像文将句柄
param lVaildNum 返回的匹配结果点个数
eturn 匹配结果点数组
*/
PointInfo* ImageMatch(FILE* pLeftImg,FILE* pRightImg,long &lVaildNum)
{
   
  long Imgwidth = 0;
  long ImgHeight= 0;
  // 获取左图像宽高,具体代码不写
   
     // 开辟一个整幅图像大小的数组
  PointInfo* pResultPt  = new  PointInfo[Imgwidth*ImgHeight];
 
  // 开始图像匹配,具体代码不写
    
  return pResultPt;
}
 

 

 

    说实话我不喜欢这种函数的设计,为什么呢?因为我觉得为了很好地避免内存泄露的话,最好遵循这样一个原则:函数外部申请的内存函数外部释放,函数内部申请的内存在函数内存释放,如果像上面的函数设计,用户往往会忘记释放 pResultPt 的内存,而且这种释放也令人感觉不自然。开始我想这样改为这样设计:

 


view plaincopy to clipboardprint?
/*! 
rief 匹配两幅图像,返回匹配结果点数组 
param pLeftImg  左图像文件句柄 
param pRightImg 右图像文件句柄 
param pResultPt 输入的匹配点数组 
param InitPtNum 输入的匹配点数组的个数 
param lVaildNum 返回的匹配结果点个数 
eturn 无 
*/ 
void ImageMatch(FILE* pLeftImg,FILE* pRightImg,PointInfo* pResultPt,long InitPtNum,long &lVaildNum)  
{  
     // 具体实现代码省去  

/*!
rief 匹配两幅图像,返回匹配结果点数组
param pLeftImg  左图像文件句柄
param pRightImg 右图像文件句柄
param pResultPt 输入的匹配点数组
param InitPtNum 输入的匹配点数组的个数
param lVaildNum 返回的匹配结果点个数
eturn 无
*/
void ImageMatch(FILE* pLeftImg,FILE* pRightImg,PointInfo* pResultPt,long InitPtNum,long &lVaildNum)
{
     // 具体实现代码省去
}
 

 

 

调用这个函数的部分代码:

 


view plaincopy to clipboardprint?
// 调用代码  
// 打开左右图像  
FILE* pLeftImg;  
FILE* pRightImg;  
long Imgwidth = 0;  
long ImgHeight= 0;  
// 获取左图像宽高,具体代码不写  
long InitPtNum = Imgwidth*ImgHeight;  
PointInfo* pResultPt  = new  PointInfo[InitPtNum];  
long lVaildNum = 0;  
ImageMatch(pLeftImg,pRightImg,pResultPt,InitPtNum,lVaildNum); 
// 调用代码
// 打开左右图像
FILE* pLeftImg;
FILE* pRightImg;
long Imgwidth = 0;
long ImgHeight= 0;
// 获取左图像宽高,具体代码不写
long InitPtNum = Imgwidth*ImgHeight;
PointInfo* pResultPt  = new  PointInfo[InitPtNum];
long lVaildNum = 0;
ImageMatch(pLeftImg,pRightImg,pResultPt,InitPtNum,lVaildNum);
 

 

 

     上面的代码符合了函数外部申请的内存函数外部释放,函数内部申请的内存在函数内存释放的原则,但是依然给人别扭的感觉,首先是要找匹配点,先得开一个整幅图的大数组(满足找匹配点的需要,担心不够用),然而匹配点往往只占图像的一小部分;其次是输入的函数的参数增多了,除了输入匹配点数组指针,还得输入数组的难度,输入参数增多往往增加了用户的使用难度,比如用户可能会搞不清楚 long InitPtNum 这个参数所代表的意义 。

 

最后我想比较理想的设计是什么呢?用户只需要输入两幅图像的文件句柄和动态数组,调用后返回这个数组就行。于是我想到了下面这个设计:

 


view plaincopy to clipboardprint?
/*! 
rief 匹配两幅图像 
param pLeftImg  左图像文件句柄 
param pRightImg 右图像文件句柄 
param  VecPt 输入和匹配点数组 
eturn 无 
*/ 
void ImageMatch(FILE* pLeftImg,FILE* pRightImg,std::vector<PointInfo> &VecPt)  
{  

/*!
rief 匹配两幅图像
param pLeftImg  左图像文件句柄
param pRightImg 右图像文件句柄
param  VecPt 输入和匹配点数组
eturn 无
*/
void ImageMatch(FILE* pLeftImg,FILE* pRightImg,std::vector<PointInfo> &VecPt)
{
}
 

这样设计,首先免去开辟和释放内存之累,其次你再也不用开辟一大块内存去应对一个不确定的情况,三是别人使用起来非常自然。

 

   由此看来,适当使用现成的动态数组结构可以使我们的设计更为合理。

补充:软件开发 , C语言 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,