1、根据项目需求,先设计出一个粗糙的类图,在后续的细化过程中,应考虑后期开发的可扩展性和易维护性,以模块为单位,尽量降低模块间的耦合度,提高聚合度,对外放出接口即可,接口中若需要传输某个类的对象,应该以指针形式传输;模块内部的类与类之间尽量保持各自的独立性。
如需要设计某个类时,无论是一个窗口类,还是一个普通类,此时你该考虑该类是不是需要做成一个静态Lib或DLL库,可能该类中维护的数据复杂,其他类都可能使用到该类中数据,为了便于函数的入参,出参方便,把该类独立出来,这样在后期开发中会轻松很多。
在细化类中的数据结构时,根据需要,恰当的细化类的数据结构,不要滥用STL对象。
2、STL对象中存储的若有类对象,建议使用类的指针存储,否则每次插入数据,都是会调用该类的拷贝构造函数的,当然了,你肯定是需要自己实现该类的拷贝函数了,实现时,一定要深拷贝。若是map中key是存储的是一个类,则必须要在该类中实现比较运算符。因为map默认是会按key值去比较排序的。
3、关于Freelibrary释放一个DLL时,若是在DLL中有自己动态new对象,Freelibrary在卸载DLL时,是不会去卸载该块内存的。
下面是一个小demo,可以尝试在有或者没有注释FreeLibrary 时,看看指针p指向的内存是否有变化(查看方法是,打开VS2008的 " Memory"窗口,根据指针p的指向的地址查看其指向的内容是否有变化)。
typedef DriverBase*(__stdcall* pFun)();
pFun FunTem = (pFun)::GetProcAddress(hMoudle, _T("GetMoudleObj"));
DriverBase* p = FunTem();
BOOL bResult = ::FreeLibrary(hMoudle);
if(p)
{
delete p;
cout << "test p" << endl;
}
4、小心删除STL中vector和deque这种顺序存储容器中元素时迭代器失效的问题在,这个问题我以前没怎么注意,这次开发过程中遇到了。
下面是删除容器中元素为某值的元素的demo
//vector<string> vectorTemp;
list<string> listTemp; //使用list,STL的迭代器就不会失效
listTemp.push_back("test1");
listTemp.push_back("test2");
listTemp.push_back("test3");
list<string>::iterator iBegin = listTemp.begin();
list<string>::iterator iEnd = listTemp.end();
string strTemp = "test2";
while(iBegin != iEnd)
{
if(!strTemp.compare(*iBegin))
{
cout << "result:" << *iBegin << endl;
list<string>::iterator iTemp = iBegin;
iBegin++;
listTemp.erase(iTemp);
continue;
}
iBegin++;
}
int iSize = listTemp.size();
cout << endl;
5、在动态库DLL与exe,或者动态库DLL与动态库DLL强烈建议,不要为了入参,出参方便,就传递STL对象。因为这样很容易出现不同执行单元间内存的分配与释放的问题,导致程序崩溃。而执行过程中若是没有导致程序崩溃,一般即使引用STL对象的作为参数,也不会有数据的返回出去的。
当然若是不存在不同执行单元中分配和释放的情况,如仅仅只返回某个单元中的STL对象中的数据,是不会有问题的。
个人的解决办法:
若真有需要传递STL对象的,可以考虑把该库做成Lib静态库,这样就不会出现上面的问题了;若是该库一定得做成DLL库,则可以考虑重新设计用到STL对象的接口,比如像C风格的函数一样,数据一个一个的传递出去,只是需要多调用几次接口(一般对外的库都是使用C函数的接口提供的,应为考虑到跨平台,不会有人使用C++提供对外的接口的)。若不这样做,仅仅只是作为自己程序内部调用的模块,可再单独做个类库,该库只负责将内存的分配和释放都在该类库中做,外面要使用到该内存,只需要调用该库提供对外面返回该内存的数据的接口和释放该内存的接口,这样就不会出现不同单元间内存的分配与释放的问题了。