C++技巧2内存管理和优秀的设计思想

1.智能指针
智能指针的使用,auto_ptr赋值时候(显式直接赋值,隐式函数参数传递,返回值传递)都会丢失所有权,原来的指针被释放了,容易发生误用原来智能指针和智能指针所有权丢失的问题。建议使用boost的scope_ptr就够了或者使用auto_ptr仅是保护作用,需要赋值的需要用boost的shared_ptr.
2.引用计数
引用计数技巧:希望多个引用使用同一份内存数据,增加引用计数就可以了,应该由最初创建它的模块来负责遍历销毁它。引用计数用了一个“写时拷贝”的技巧,是一个lazyy caculate的经典例子。但是引用计数有一个问题,就是一个地方对它改变了,其它地方也会跟着改变,所以需要加入一个赋值时是否拷贝的设置就可以区分了,或者 需要赋值拷贝的容器根本不使用引用计数,使用引用计数的不对其进行拷贝修改用profile查看使用的频繁,和赋值的频率,确定是否用引用计数管理内存

3.优先使用优秀的面向对象继承/管理类重构/抽象多态组合设计模式之路-代理类
代理类,分为内部代理,就是嵌套到类内部因为只有外部类来使用。代理类用了设计模式中的代理模式,对于类似引用计数的,本身不支持引用计数,但是可用通过一个封装包装的代理类,有代理类来管理类型的指针内存和引用计数,其实代理类可以写成模板形式,这样就可以为其它类来提供引用计数功能。

4.面向过程设计存在的优点
当面向对象设计比较复杂且不好维护时候,那么需要考虑用面向过程的设计方法。例如超过一个参数类型为多态类的时候,面向对象的无论是typeid确定类型类型码确定类型;
类的派生体系也比较复杂,还是代码的冗余都难以消除;那么就要考虑是使用C面向对象的设计方法,函数指针的形式区分多态函数,制作一个管理器来管理多态的类型,
将多态类型的类型码Type1,Type2作为管理器map的key值,value是函数指针。这样数据放置在各个类中,算法封装到C风格的Utility函数,整个架构就比较清晰和易于维护了。

5.当继承复用性不够好的时候,可以采用template模板的泛型设计模式,得到更加通用优秀的组件。
 
5.用代码来实现易于正确使用难以错误使用的组件
使用面向未来的设计思想,但是不要过分设计,为了软件的可靠性、健壮性、安全性、可读性、可扩展性和可复用性而去设计。不是通过文档规范,而是通过代码的设计来实现。
使得代码易于正确使用,难以错误使用。比如通过单例模式,通过禁止赋值拷贝构造函数来避免软件间赋值。例如避免基类指针间用*取得对象赋值,那么可以通过声明为抽象基类
避免这样的操作。通过声明为虚析构函数,避免未来继承出现的内存泄露。通过全局对象指针,而不是全局对象变量形式避免构造函数导致的异常。

6.C和C++之间正确调用需要注意的问题  
注意C/C++之间相互调用,C++环境中正确连接C库函数,需要
#ifdef _cplusplus
extern "c "{
#endif
...
#ifdef _cplusplus
}
#endif这样的结构,是说明用C方式的编译函数,汇编语言也适用。
注意静态变量初始化,需要C++风格的Main函数,而不是C的,需要注意构造函数调用时机,是否会因为相互依赖而导致构造函数失败。
注意结构体,C++的不含虚成员函数的结构体才是和C一样内存对齐的,否则是不对齐的。
C++new delete,C malloc free不能混淆了,且new 或new[]失败了会返回NULL,delete delete[],free多次空指针是正常的,但是释放野指针却是致命的。

7.使用STL,容器,迭代器和算法
1)注意迭代器删除
2)结构体key值需要重载<运算符
3)vector list的std::find进行查找
4)使用sort排序函数避免冒泡排序写法
5)不要memset包含stl容器的结构体
6)使用auto_ptr赋值和参数传递要非常小心,只能用智能指针的地址来处理,不然所有权会丢失,可以使用boost的scope_ptr和shared_ptr。
7)boost的order_map比hash_map效率高,hash_map比map高,超过1千行就应该使用order_map的了。

你可能感兴趣的:(C++技巧2内存管理和优秀的设计思想)