本周学习心得

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

  
  
  
  
  1. class MyClass  
  2. {  
  3. public:  
  4.     MyClass()  
  5.     {  
  6.         for (int i=0; i<SIZE; ++i)  
  7.         {  
  8.             array[i] = i+1;  
  9.         }  
  10.     }  
  11.     void PrintArray()  
  12.     {  
  13.         for (int i=0; i<SIZE; ++i)  
  14.         {  
  15.             cout << array[i] <<endl;  
  16.         }  
  17.     }  
  18. private:  
  19.     enum { SIZE = 100 };  
  20.     int array[SIZE];  
  21. }; 

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

  
  
  
  
  1. class MyClass  
  2. {  
  3. public:  
  4.     MyClass()  
  5.     {  
  6.         for (int i=0; i<SIZE; ++i)  
  7.         {  
  8.             array[i] = i+1;  
  9.         }  
  10.     }  
  11.  
  12.     void PrintArray()  
  13.     {  
  14.         for (int i=0; i<SIZE; ++i)  
  15.         {  
  16.             cout << array[i] <<endl;  
  17.         }  
  18.     }  
  19. private:  
  20.     static const int SIZE = 100;  
  21.     int array[SIZE];  
  22. }; 

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

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

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

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

  
  
  
  
  1. void GetMemory(char *p, int num)  
  2. {  
  3.     p = (char*) malloc(sizeof(char) * num);  
  4. }  
  5.  
  6. int main()  
  7. {  
  8.     char *str = NULL;  
  9.     GetMemory(str, 100);  
  10.     strcpy(str, "hello world");  
  11.     return 0;  

可以改成如下:

  
  
  
  
  1. void GetMemory(char **p, int num)  
  2. {  
  3.     *p = (char*) malloc(sizeof(char) * num);  
  4. }  
  5.  
  6. int main()  
  7. {  
  8.     char *str = NULL;  
  9.     GetMemory(&str, 100);  
  10.     strcpy(str, "hello world");  
  11.     cout << str <<endl;  
  12.     free(str);  
  13.     str = NULL;  
  14.     return 0;  

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

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

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

  
  
  
  
  1. #include <iostream>  
  2. #include <set>  
  3. using namespace std;  
  4.  
  5. template <class T>  
  6. class RuntimeCmp  
  7. {  
  8. public:  
  9.     enum cmp_mode {NORMAL,REVERSE};  
  10. private:  
  11.     cmp_mode mode;  
  12. public:  
  13.     RuntimeCmp(cmp_mode m = NORMAL) : mode(m)  
  14.     {  
  15.  
  16.     }  
  17.  
  18.     bool operator () (const T& t1, const T& t2)  
  19.     {  
  20.         return mode == NORMAL ? t1 < t2 : t2 < t1;  
  21.     }  
  22.  
  23.     bool operator == (const RuntimeCmp& rhs)  
  24.     {  
  25.         return mode == rhs.mode;  
  26.     }  
  27. };  
  28.  
  29. typedef set<int, RuntimeCmp<int> > IntSet;  
  30.  
  31. void fill(IntSet& set)  
  32. {  
  33.     set.insert(4);  
  34.     set.insert(7);  
  35.     set.insert(5);  
  36.     set.insert(1);  
  37.     set.insert(6);  
  38.     set.insert(2);  
  39.     set.insert(5);  
  40. }  
  41. void PrintElements(IntSet& set)  
  42. {  
  43.     IntSet::iterator iter;  
  44.     for (iter = set.begin(); iter != set.end(); ++iter)  
  45.     {  
  46.         cout << *iter << endl;  
  47.     }  
  48. }  
  49. int main()  
  50. {  
  51.     IntSet coll1;  
  52.     fill(coll1);  
  53.     PrintElements(coll1);  
  54.  
  55.     RuntimeCmp<int> reverse_order(RuntimeCmp<int>::REVERSE);  
  56.  
  57.     IntSet coll2(reverse_order);  
  58.     fill(coll2);  
  59.     PrintElements(coll2);  
  60.  
  61.     coll1 = coll2;  
  62.     coll1.insert(3);  
  63.     PrintElements(coll1);  
  64.  
  65.     if (coll1.value_comp() == coll2.value_comp())  
  66.     {  
  67.         cout << "same sorting criterion" << endl;  
  68.     }  
  69.     return 0;  

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

  
  
  
  
  1. BSTR CCardScanCtrl::GetName(void)  
  2. {  
  3.     AFX_MANAGE_STATE(AfxGetStaticModuleState());  
  4.     CString strResult;  
  5.     strResult = Scan::getInstance().m_strName;  
  6.     return strResult.AllocSysString();  

  于是,改为如下代码:

  
  
  
  
  1. BSTR CCardScanCtrl::GetName(void)  
  2. {  
  3.     AFX_MANAGE_STATE(AfxGetStaticModuleState());  
  4.     CString strResult;  
  5.     strResult = Scan::getInstance().m_strName;  
  6.     CComBSTR bstrResult(strResult);  
  7.     return bstrResult;  

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

  
  
  
  
  1. ~CComBSTR()   
  2. {   
  3. ::SysFreeString(m_str);   

 

你可能感兴趣的:(职场,休闲,学习心得)