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)
- {
- *p = (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);
- }