本周学习心得

本文探讨了C++编程中的一些最佳实践,包括使用静态常量成员而非枚举、正确处理指针内存分配与释放、避免内存泄漏、以及如何在运行时指定排序准则等。文章通过具体示例详细说明了这些技巧的正确应用。

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->classMyClass
{
public:
MyClass()
{
for(inti=0;i<SIZE;++i)
{
array[i]
=i+1;
}
}
voidPrintArray()
{
for(inti=0;i<SIZE;++i)
{
cout
<<array[i]<<endl;
}
}
private:
enum{SIZE=100};
intarray[SIZE];
};

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->classMyClass
{
public:
MyClass()
{
for(inti=0;i<SIZE;++i)
{
array[i]
=i+1;
}
}

voidPrintArray()
{
for(inti=0;i<SIZE;++i)
{
cout
<<array[i]<<endl;
}
}
private:
staticconstintSIZE=100;
intarray[SIZE];
};

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

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->BYTE*pBuffer=newBYTE[len];
if(pBuffer==NULL)
{
//分配内存失败
delete[]pBuffer;
pBuffer
=NULL;//防止成为“野指针”
return;
}
//endofif

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->voidGetMemory(char*p,intnum)
{
p
=(char*)malloc(sizeof(char)*num);
}

intmain()
{
char*str=NULL;
GetMemory(str,
100);
strcpy(str,
"helloworld");
return0;
}

可以改成如下:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->voidGetMemory(char**p,intnum)
{
*p=(char*)malloc(sizeof(char)*num);
}

intmain()
{
char*str=NULL;
GetMemory(
&str,100);
strcpy(str,
"helloworld");
cout
<<str<<endl;
free(str);
str
=NULL;
return0;
}

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->CStringScan::EncodeImage()
{
//对生成的图片进行Base64编码
ZBase64zBase;
//图片编码
CxImageimage;//定义一个CxImage对象
image.Load(this->m_strImgPath,CXIMAGE_FORMAT_JPG);//先装载jpg文件,需要指定文件类型
longsize=0;//得到图像大小
BYTE*buffer=0;//存储图像数据的缓冲
image.Encode(buffer,size,CXIMAGE_FORMAT_JPG);//把image对象中的图像以type类型数据copy到buffer
stringstrTmpResult=zBase.Encode(buffer,size);//对生成的图片进行Base64编码
if(buffer!=NULL)
{
//释放缓冲区
delete[]buffer;
buffer
=NULL;
}
//返回编码后的图片数据
CStringresult;
result
=strTmpResult.c_str();
returnresult;
}

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include<iostream>
#include
<set>
usingnamespacestd;

template
<classT>
classRuntimeCmp
{
public:
enumcmp_mode{NORMAL,REVERSE};
private:
cmp_modemode;
public:
RuntimeCmp(cmp_modem
=NORMAL):mode(m)
{

}

booloperator()(constT&t1,constT&t2)
{
returnmode==NORMAL?t1<t2:t2<t1;
}

booloperator==(constRuntimeCmp&rhs)
{
returnmode==rhs.mode;
}
};

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

voidfill(IntSet&set)
{
set.insert(4);
set.insert(7);
set.insert(5);
set.insert(1);
set.insert(6);
set.insert(2);
set.insert(5);
}
voidPrintElements(IntSet&set)
{
IntSet::iteratoriter;
for(iter=set.begin();iter!=set.end();++iter)
{
cout
<<*iter<<endl;
}
}
intmain()
{
IntSetcoll1;
fill(coll1);
PrintElements(coll1);

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

IntSetcoll2(reverse_order);
fill(coll2);
PrintElements(coll2);

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

if(coll1.value_comp()==coll2.value_comp())
{
cout
<<"samesortingcriterion"<<endl;
}
return0;
}

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->BSTRCCardScanCtrl::GetName(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CStringstrResult;
strResult
=Scan::getInstance().m_strName;
returnstrResult.AllocSysString();
}
于是,改为如下代码:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->BSTRCCardScanCtrl::GetName(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CStringstrResult;
strResult
=Scan::getInstance().m_strName;
CComBSTRbstrResult(strResult);
returnbstrResult;
}

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->~CComBSTR()
{
::SysFreeString(m_str);
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值