??xml version="1.0" encoding="utf-8" standalone="yes"?>
不过快速开发时Q我们ƈ不会(x)局限于一U语aQ很多时候都是用多U语aQ实C个强大又l丽的UI的YӞ而且可以保证开发速度很快?
每一U语a都有独特的优势,有优势的部分恰恰是很适合应用的场景,因此~码实现方便快速。ƈ不是说C++开发程序就一定很慢,也不是说C#开发程序就一定快。如果要做偏底层的功能,往往C++实现hq是很快Q而且E序的执行效率也是很高的。对于底层的操作Q用C#{语a来说Q就非常不方ѝ比如调用个pȝAPI函数QC/C++包含一个头文gQ然后直接写函数名称卛_Q而其他语a则比较麻?ch)?jin)。因Z们要通过一层函数库的封装间接调用底层API的,所以也很ȝ(ch)?jin)?
不过Q正是封装的多,使用的库多,对于C#q类语言来说Q实现界面就很快?jin)。所以说Q做UI是他们的长处Q所以也很简单?
那么既然如此Q我们就C++和C#l合来用就很好Q这叫做强强联合Q选择C#也是因ؓ(f)语法上和C++很相|VBq些语言语法和C++相差很大Q不?fn)惯?/font>
那么C++做底层功能封装和C#界面开发如何合v来呢Q这个估计是大家最为关?j)的一个问题吧。在实现界面ӞC#可以选择wpf做界面,非常的不错。学?fn)难度也不大QC#代码Q对于C++熟?zhn)的hQ也觉得很好掌握。C++从业者去使用C#问题不大Q只是会(x)多吐槽一下C#的不方便操作指针之类的,不过C#的string实Z错的Q我蛮喜Ƣ?
C++装代码成dll形式提供lC(j)#{语a使用。C++代码中,你可以尽情的使用cL完成功能Q只是在导出函数Ӟ只要提供C语言的函敎ͼ而不要将cd出,不徏议这么做。而导出函数时Qؓ(f)?jin)让更多语言方便使用dllQ导出函C用C调用U定导出函数。一般语a都支持标准C函数调用U定?
更多的细节,׃在本文讲q。这里就是概q性的l大家一个印象,让你知道写程序还可以q样玩哦。不要将自己的思维局限于一U语aQ不要再为学?fn)哪一U语a而纠l,也不要ؓ(f)哪一U语a好而争执?
不过Q初学者总要选定一U语a作ؓ(f)出发Q而我的徏议时Q学?fn)时可能基而全面的学习(fn)。在入门的时候,相对来说是比较沉得下?j)学习(fn)的。所以选择学习(fn)C++作ؓ(f)入门语言是非怸错的选择。当你C++学的不错的时候,再学其他语言做应用开发,都是L掌握的。但是如果工作了(jin)Q再来学?fn)C++Q精力有限,而且很难?rn)下心(j)学习(fn)又大又全又l的C++?
然而做底层开发时QC++无疑是一个很好的选择。如果C++借用界面库,自然也是可以做很不错的UI的。其他语a之所以可以快速开发,也就是有很多库的支持。当C++的第三方库多?jin),开发速度自然也是很不错的?
如果你有一些不错的xQ就到C++技术网分n下吧。我?x)仔l阅L一个字透露出来的气息,l你分n我的相关l验Q尽量开阔你的思维范围Q一赯步?
什么是RAII以及(qing)几个例子
在C++{面向对象语a中,Z(jin)理局部资源的分配以及(qing)释放(resource allocation and deallocation)Q实现异常安?exception-safe)、避免内存泄露等问题QC++之父Bjarne Stroustrup发明?jin)一U叫?#8221;初始化中获取资源“ (RAII, Resource Acquisition Is InitializationQ也可以叫做Scope-Bound Resource Management)的技术。简单来_(d)它的目的是利用一个局部对象,在这个对象的构造函数内分配资源Q然后在其析构函数内释放资源。这P当这个局部对象退Z用域Ӟ它所对应的的资源卛_自动释放。在实现上,它通常有三个特点:(x)
创徏一个特D类Q在其构造函数初甌资源;
装目标对象Q将甌资源的目标对象作个特D类的成员变?
在这个类的析构函数内Q释放资源?br />
一个典型的例子是标准库中提供的模板类std::auto_ptr。如在《C++E序设计语言?《The C++ Programming Language, Special Edition? Bjarne Stroustrup著,裘宗燕译)中第327|描述?strong>SAT{案
1: template
2: class std::auto_ptr {
3:
4: public:
5: //在构造函CQ获得目标指针的理?br />
6: explicit auto_ptr(X *p = 0) throw() { ptr = p; }
7: //在析构函CQ释攄标指?br />
8: ~auto_ptr() throw() { delete ptr; }
9:
10: //...
11:
12: //重装*?>q算W,使auto_ptr对象像目标指针ptr一样?br />
13: X& operator*() const throw() { return *ptr; }
14: X* operator->() const throw() { return ptr; }
15:
16: //攑ּ对目标指针的理?br />
17: X* release() throw() { X* t = ptr; ptr = 0; return t; }
18:
19: private:
20: X *ptr;
21: };
惌使用它,非常单,例如
1: #include
2:
3: void func()
4: {
5: std::auto_ptr p(new int);
6:
7: //use p just like ptr
8:
9: return;
10: }
另一个例子,是利用GCC中的cleanup attribute。它可以指定一个函敎ͼ在该变量退Z用域时可以执行。例如Wikipedia上提到的?br />
1: #define RAII_VARIABLE(vartype,varname,initval,dtor) \
2: void _dtor_ ## varname (vartype * v) { dtor(*v); } \
3: vartype varname __attribute__((cleanup(_dtor_ ## varname))) = (initval)
我们可以q样使用Q例?br />
1: void example_usage() {
2: RAII_VARIABLE(FILE*, logfile, fopen("logfile.txt", "w+"), fclose);
3: fputs("hello logfile!", logfile);
4: }
q有一个例子,是在刘未鹏的博客文章”C++11 (?qing)现代C++风格)和快速P代式开?#8220;中的”资源理“一节中看到的,他借助C++11的std::function实现?jin)这一Ҏ(gu)。感兴趣的码友可以到他博客内阅读?br />
W者采用的Ҏ(gu)
对于new/deleteQ用上面提到的std::auto_ptr可以了(jin)Q但是对于new/delete[]一个动态的一l数l,甚至二维数组Qauto_ptr无能ؓ(f)力了(jin)。而且在一些项目中Q特别是一些有着(zhn)久历史的代码中Q还存在着使用malloc, newL(fng)的现象。所以笔者设计了(jin)一个auto_free_ptrc,实现目标资源的自动回收。它的实现比较简单,只利用了(jin)RAII的第三个特点——”在类的析构函数内释放资源”Q但有一个优Ҏ(gu)可以在申请堆内存代码前?strong>托福{案
代码如下Q?br />
1: //auto_free_ptr is only used for automation free memory
2: template
3: class auto_free_ptr
4: {
5: public:
6: typedef enum {invalid, new_one, new_array, alloc_mem} EFLAG;
7: auto_free_ptr() { initialize(); }
8: ~auto_free_ptr(){ free_ptr(); }
9:
10: ///set the pointer needed to automatically free
11: inline void set_ptr(T** new_ptr_address, EFLAG new_eflag)
12: { free_ptr(); p_ptr = new_ptr_address; eflag = new_eflag; }
13:
14: ///give up auto free memory
15: inline void give_up() { initialize(); }
16:
17: protected:
18: inline void initialize() { p_ptr = NULL; eflag = invalid; }
19: inline void free_ptr() throw()
20: {
21: if(!p_ptr || !(*p_ptr)) return;
22:
23: switch(eflag)
24: {
25: case alloc_mem: { free(*p_ptr), (*p_ptr) = NULL, p_ptr = NULL; break; }
26: case new_one: { delete (*p_ptr), (*p_ptr) = NULL, p_ptr = NULL; break; }
27: case new_array: { delete[] (*p_ptr),(*p_ptr) = NULL, p_ptr = NULL; break; }
28: }
29: }
30:
31: protected:
32: T** p_ptr; //!< pointer to the address of the set pointer needed to automatically free
33: EFLAG eflag; //!< the type of allocation
34:
35: private:
36: DISABLE_COPY_AND_ASSIGN(auto_free_ptr);
37: };
Z(jin)使用方便Q封装两个宏Q?br />
1: // auto-free macros are mainly used to free the allocated memory by some local variables in the internal of function-body
2: #define AUTO_FREE_ENABLE( class, ptrName, ptrType ) \
3: auto_free_ptr auto_free_##ptrName; \
4: auto_free_##ptrName.set_ptr(&ptrName,auto_free_ptr::ptrType)
5:
6: #define AUTO_FREE_DISABLE( ptrName ) auto_free_##ptrName.give_up()
使用h很简单,例如
1: void func(int nLftCnt, int nRhtCnt)
2: {
3: if (!nLftCnt && !nRhtCnt)
4: return;
5:
6: unsigned *pLftHashs = NULL;
7: unsigned *pRhtHashs = NULL;
8:
9: //在申请堆内存之前Q用auto_free_ptr
10: AUTO_FREE_ENABLE(unsigned, pLftHashs, new_array);
11: AUTO_FREE_ENABLE(unsigned, pRhtHashs, new_array);
12:
13: //....
14:
15: if (nLftCnt)
16: {
17: pLftHashs = new unsigned[nLftCnt];
18: //...a
19: }
20:
21: if (nRhtCnt)
22: {
23: pRhtHashs = new unsigned[nRhtCnt];
24: //...b
25: }
26:
27: //....
28:
29: if (...)
30: {
31: //因ؓ(f)下面q个函数可以释放资源Q所以在它前面放弃对目标指针的管理权
32: AUTO_FREE_DISABLE(pLftHashs);
33: AUTO_FREE_DISABLE(pRhtHashs);
34:
35: //q个函数可以释放资源
36: free_hash_arrays(pLftHashs, pRhtHashs);
37: }
38: }
同样的,有时我们需要申请一个动态二l数l,所以也实现一个对应的auto_free_2D_ptr
1: //auto_free_2D_ptr is only used for automation free memory of 2D array
2: template
3: class auto_free_2D_ptr
4: {
5: public:
6: typedef enum {invalid, new_one, new_array, alloc_mem} EFLAG;
7: auto_free_2D_ptr() { initialize(); }
8: ~auto_free_2D_ptr() { free_ptr(); }
9:
10: ///set the pointer needed to automatically free
11: inline void set_ptr( T** new_ptr_address,EFLAG new_eflag, int new_length_row )
12: { free_ptr(); p_ptr = new_ptr_address; eflag = new_eflag; length_row = new_length_row; }
13:
14: //give up auto free memory
15: inline void give_up() { initialize(); }
16:
17: protected:
18: inline void initialize() { p_ptr = NULL; eflag = invalid; length_row = 0;}
19: inline void free_ptr() throw()
20: {
21: if(!p_ptr || !(*p_ptr)) return;
22:
23: for(int i = 0; i < length_row; i++)
24: {
25: if(!(*p_ptr)[i]) continue;
26: switch(eflag)
27: {
28: case alloc_mem: { free((*p_ptr)[i]); break; }
29: case new_one: { delete (*p_ptr)[i]; break; }
30: case new_array: { delete[] (*p_ptr)[i]; break; }
31: }
32: (*p_ptr)[i] = NULL;
33: }
34: switch(eflag)
35: {
36: case alloc_mem: { free((*p_ptr)); break; }
37: default: { delete[] (*p_ptr); break; }
38: }
39: (*p_ptr) = NULL, p_ptr = NULL;
40: }
41:
42: protected:
43: T** p_ptr; //!< pointer to the address of the set pointer needed to automatically free
44: EFLAG eflag; //!< the type of allocation
45: int length_row; //!< the row length such as ptr[length_row][length_col]
46:
47: private:
48: DISABLE_COPY_AND_ASSIGN(auto_free_2D_ptr);
49: };
50:
51: #define AUTO_FREE_2D_ENABLE( class, ptrName, ptrType, rowNum ) \
52: auto_free_2D_ptr auto_free_##ptrName; \
53: auto_free_##ptrName.set_ptr(&ptrName,auto_free_2D_ptr::ptrType, rowNum)
54:
55: #define AUTO_FREE_2D_DISABLE( ptrName ) AUTO_FREE_DISABLE( ptrName )
下面是个例子
1: void func(int row, int col)
2: {
3: if (!row && !col)
4: return;
5:
6: int **ptr = new int*[ row ];
7: for( int r = 0; r < row; ++r ) { ptr[r] = new int[ col ];}
8:
9: AUTO_FREE_2D_ENABLE( int, ptr, new_array, row );
10:
11: //....
12: }
到这里就l束?jin),有些码友可能会(x)说Q何必这么麻?ch),boost内有很多指针供选择Q用share_ptr, scoped_ptr, scoped_arrayQunique_ptr, auto_ptr 中的一个不p?jin)? 没错!如果你正在开发的代码中,允许用boostQƈ且在相关E序接口l一都用指针来管理、不?x)用到源对象指针的话Q当然优先选boostQ但是当你的代码中由于历史原因,有些接口不可变更Q且new/delete, malloc/free都存在,而且依然需要用源对象指针来完成大部分工作Ӟ不妨试试我设计的q个阉割版的scoped_ptr/scoped_array。MQ根据自q实际情况来选择合适的Ҏ(gu)Q如果标准方案不适用Q就自己写一?strong>托福{案