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];
};
{
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];
};
{
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
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 ;
}
{
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 ;
}
{
* 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;
}
{ // 对生成的图片进行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 ;
}
#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();
}
于是,改为如下代码:
{
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;
}
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString strResult;
strResult = Scan::getInstance().m_strName;
CComBSTR bstrResult(strResult);
return bstrResult;
}
可是,这样的后果是在JavaScript中访问Name属性时,出现内存访问错误的bug,原因就是CComBSTR的析构函数:
~
CComBSTR()
{
::SysFreeString(m_str);
}
{
::SysFreeString(m_str);
}