本周学习心得

1,《高质量C++/C 编程指南》第5章第4节讲到类中的常量时,作者是推荐用enum来实现

class  MyClass
{
public :
    MyClass()
    {
        
for  ( int  i = 0 ; i < SIZE;  ++ i)
        {
            array[i] 
=  i + 1 ;
        }
    }
    
void  PrintArray()
    {
        
for  ( int  i = 0 ; i < SIZE;  ++ i)
        {
            cout 
<<  array[i]  << endl;
        }
    }
private :
    
enum  { SIZE  =   100  };
    
int  array[SIZE];
};

但我个人更喜欢用static const成员来实现:

class  MyClass
{
public :
    MyClass()
    {
        
for  ( int  i = 0 ; i < SIZE;  ++ i)
        {
            array[i] 
=  i + 1 ;
        }
    }

    
void  PrintArray()
    {
        
for  ( int  i = 0 ; i < SIZE;  ++ i)
        {
            cout 
<<  array[i]  << endl;
        }
    }
private :
    
static   const   int  SIZE  =   100 ;
    
int  array[SIZE];
};

2,不要将正常值和错误标志混在一起返回,正常值用输出参数获得,错误标志用return语句返回。

3,在使用内存前检查指针是否为NULL

BYTE  * pBuffer  =   new  BYTE[len];
if  (pBuffer  ==  NULL)
{
// 分配内存失败
    delete [] pBuffer;
    pBuffer 
=  NULL;  // 防止成为“野指针”
     return ;
}
// end of if

4,如果函数的参数是一个指针,则不要指望用该指针去申请动态内存,下面示例中str依旧是NULL.原因在于调用函数时总是会为每个参数制作临时副本,指针也不例外,因此GetMemory里申请了内存,只是把str指针的副本所指的内存地址改变了,但str本身没变。而每执行一次GetMemory就会泄露一块内存,因为那个副本指针指向的内存没有free

void  GetMemory( char   * p,  int  num)
{
    p 
=  ( char * ) malloc( sizeof ( char *  num);
}

int  main()
{
    
char   * str  =  NULL;
    GetMemory(str, 
100 );
    strcpy(str, 
" hello world " );
    
return   0 ;
}

可以改成如下:

void  GetMemory( char   ** p,  int  num)
{
    
* =  ( char * ) malloc( sizeof ( char *  num);
}

int  main()
{
    
char   * str  =  NULL;
    GetMemory(
& str,  100 );
    strcpy(str, 
" hello world " );
    cout 
<<  str  << endl;
    free(str);
    str 
=  NULL;
    
return   0 ;
}

5,在客户现场测试时发现ActiveX控件加载运行后,出现内存泄露的问题,几番测试后发现是是调用 CxImage库的Encode方法时犯了个错误,没有释放图像数据缓冲区,修改后代码如下:

CString Scan::EncodeImage()
{
// 对生成的图片进行Base64编码
    ZBase64 zBase;
    
// 图片编码
    CxImage  image;    //  定义一个CxImage对象    
    image.Load( this -> m_strImgPath, CXIMAGE_FORMAT_JPG);    // 先装载jpg文件,需要指定文件类型
     long  size = 0 ; // 得到图像大小
    BYTE *  buffer = 0 ; // 存储图像数据的缓冲
    image.Encode(buffer,size,CXIMAGE_FORMAT_JPG); // 把image对象中的图像以type类型数据copy到buffer
     string  strTmpResult = zBase.Encode(buffer,size);  // 对生成的图片进行Base64编码
     if  (buffer  !=  NULL)
    {
// 释放缓冲区
        delete [] buffer;
        buffer 
=  NULL;
    }
// 返回编码后的图片数据
    CString result;
    result 
=  strTmpResult.c_str();
    
return  result;
}

6,《C++标准程序库》第6章第5节,运行时指定排序准则。

#include  < iostream >
#include 
< set >
using   namespace  std;

template 
< class  T >
class  RuntimeCmp
{
public :
    
enum  cmp_mode {NORMAL,REVERSE};
private :
    cmp_mode mode;
public :
    RuntimeCmp(cmp_mode m 
=  NORMAL) : mode(m)
    {

    }

    
bool   operator  () ( const  T &  t1,  const  T &  t2)
    {
        
return  mode  ==  NORMAL  ?  t1  <  t2 : t2  <  t1;
    }

    
bool   operator   ==  ( const  RuntimeCmp &  rhs)
    {
        
return  mode  ==  rhs.mode;
    }
};

typedef 
set < int , RuntimeCmp < int >   >  IntSet;

void  fill(IntSet &   set )
{
    
set .insert( 4 );
    
set .insert( 7 );
    
set .insert( 5 );
    
set .insert( 1 );
    
set .insert( 6 );
    
set .insert( 2 );
    
set .insert( 5 );
}
void  PrintElements(IntSet &   set )
{
    IntSet::iterator iter;
    
for  (iter  =   set .begin(); iter  !=   set .end();  ++ iter)
    {
        cout 
<<   * iter  <<  endl;
    }
}
int  main()
{
    IntSet coll1;
    fill(coll1);
    PrintElements(coll1);

    RuntimeCmp
< int >  reverse_order(RuntimeCmp < int > ::REVERSE);

    IntSet coll2(reverse_order);
    fill(coll2);
    PrintElements(coll2);

    coll1 
=  coll2;
    coll1.insert(
3 );
    PrintElements(coll1);

    
if  (coll1.value_comp()  ==  coll2.value_comp())
    {
        cout 
<<   " same sorting criterion "   <<  endl;
    }
    
return   0 ;
}
 

7,我讨厌C++有两个原因,一个是字符串,一个是内存泄漏。这不,今天又犯了一个错误,复审代码时,读到下面的AllocSysString()时,需要调用方用SysFreeString来释放,而ActiveX控件嵌入IE后,在JavaScript代码中又该如何释放呢?

BSTR CCardScanCtrl::GetName( void )
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    CString strResult;
    strResult 
=  Scan::getInstance().m_strName;
    
return  strResult.AllocSysString();
}
  于是,改为如下代码:
BSTR CCardScanCtrl::GetName( void )
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    CString strResult;
    strResult 
=  Scan::getInstance().m_strName;
    CComBSTR bstrResult(strResult);
    
return  bstrResult;
}

可是,这样的后果是在JavaScript中访问Name属性时,出现内存访问错误的bug,原因就是CComBSTR的析构函数:

~ CComBSTR() 

::SysFreeString(m_str); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值