l织和策略问?/span>
Q? 了解哪些东西不应该标准化
注释不是多好Q应该注意实用原则,主要用来解释Ҏ和原?br />
Q? 在高警告U别下编译,理解q排除所有的警告
如果引用的第三方库有警告Q可以用自定义的头文件包含这个库的头文gQ在自定义头文g中忽略这些警告?br />如:
#pragma warning(push)//保存当前的警?br />#pragma warning(disable:4512)
#pragma warning(disable:4180)
#include <boost/lambda/lambda.hpp>//W三方头文g
#pragma warning(pop)//恢复C前的警告
Q? 使用自动构徏pȝ
使用单操作的自动化构?br />
Q? 使用版本控制pȝ
CVS。不要让文g长时间登出,保d的代码不会媄响构建成?br />
Q? 在代码审查上投入
更多的关注有助于提高质量。亮q代码Q阅d人的代码?br />
设计风格
不成熟的优化是程序涉及中的万恶之?br />Q? 一个实体应该只有一个紧凑的职责
一ơ只解决一个问?br />
Q? 正确、简单和清晰W一
单就是美QKeep It Simple SoftwareQKISSQ?br />使用最单的有效技术?br />
Q? ~程中应该知道何时和如何考虑可~?br />集中_֊改善法的O(N)复杂性,而不是进行小型的优化?br />要时M解算法的实际复杂?br />
Q? 不要q行不成熟的优化
决不要过早进行优化,再三试Q然后在必要的时候进行优?br />让一个正的E序更快Q比让一个快速的E序正确Q要Ҏ的多?br />优化之前应进行度量,度量之前必须定优化的目标?br />
Q?不要q行不成熟的劣化
放松自己Q轻杄E?br />引用传递代替g?br />使用前缀++代替后缀++.
使用初始化列表代替构造函C赋?br />使用抽象和库
Q?0 量减少全局和共享数?br />׃nҎD冲突Q增加耦合?br />用通信方式代替数据׃n
量降低c间的耦合Q减交?br />
Q?1 隐藏信息
不要从Q何提供抽象的实体中公开数据
Q?2 懂得何时和如何进行ƈ发性编E?Q? 我没多少l验Q难以理解)
避免死锁Q活锁和恶性竞争条?br />
Q?3 保资源为对象所拥有Q用显式的RAII和智能指?br />资源获取卛_始化QRAIIQ?br />分配资源后立卌l属d象?br />永远不要在一条语句中分配一个以上的资源
当需要配对的获取/释放函数调用Ӟ都应该将资源装在一个对象中。注意复制构造和赋值操作,以及自n赋?
~程风格
Q?4 宁要~译时和q接旉误,也不要运行时错误
能在~译时做的事׃要推q到q行时?br />
Q?5 U极使用const
当知道某个g会改变时把它设为const。把const变成定义值时的默认选项
使用mutable
Q?6 避免使用?br />只在几个无法避免的地方用:
#include 保护W?br />#ifdef?if defined
assert实现
Q?7 避免使用数
使用W号名称代替它,W号名称易于理解和维?br />使用const,枚Dcdzd?br />
Q?8 可能局部地声明变量
变量的作用域小好Q生存期短好
Q?9 L初始化变?br />初始化数l和l构的简单方法:
ing total[100] = {0};
struct Data
{
int i;
double d;
char szName[10];
};
Data d={0};
注意Qvolatile型数据不需要程序对其进行初始化
Q?0 避免函数q长Q避免嵌套过?br />
Q?1 避免跨编译单元的初始化依?br />保持初始化顺?br />量避免名称I间U的变量
Q?2 量减少定义性依赖。避免@环依?br />如果可以用前向声明就不要#include
只有两种情况需要某个类的完整定义:
1 需要知道该cȝ大小
2 需要命名或者调用该cȝ成员
打破循环的一个方法就是,不要让高层模块依赖低层模块,而是让两者都依赖于抽?br />
Q?3 头文件应该自l自?Q? 一值对什么时候应该包含头文g很迷惑,好好理解一下#22和#23Q?br />应该保所~写的每个头文g都能够独自编译,卛_需要用到某个头文g中的内容Ӟ只需要包含此文gQ而不需要包含其他的文g?br />模板是在其定义处~译的,但非独立名称或者类型要{到模板实例化时才编译?br />
Q?4L~写内部Qinclude保护W,决不要编写外部#include保护W?
//for foo.h
#ifndef FOO_H_INCLUDED_
#define FOO_H_INCLUDED_
//......
#endif
函数与操作符
Q?5 正确地选择通过|Q智能)指针或引用传递参?br />
Q?6 保持重蝲操作W的自然语义
Q?7 优先使用术操作W和赋值操作符的标准Ş?br />定义了a+b 也应该定义a+=b.q且用用+=来定?.
Q?8 优先使用++和-Q的标准形式。优先调用前~形式
应该用前~形式实现后缀形式
T& T::operator++() //前缀形式
{
//执行递增
return *this;
}
T T::operator++(int) //后缀形式
{
T old(*this); //保存旧?br />++*this;
return old;
}
Q?9 考虑重蝲以避免隐含类型{?br />奥卡姆剃刀原理Q如无必要勿增对象。重载会引v临时对象的创建?br />
Q?0 避免重蝲&& ||和,
因ؓ内置版本的特D之处在于:从左到右求|Q对&& ||Q短路求?br />而函数参数L会对所有参数进行求|且求值顺序是不确定的?br />
Q?1 不要~写依赖于函数参数求值顺序的代码
函数参数的求值顺序是不确定的
cȝ设计与?/span>
软g开发最重要的一个方面就是弄清楚自己要构建的是什么?br />Q?2 弄清所要编写的是哪U类
值类 模仿内置cd
基类 构成cdơ结?br />traitsc?br />{略c?br />异常c?br />附属c?br />
Q?3 用小cM替巨c?br />分而治之:类易于~写、测试和使用
Q?4 用组合代替?br />l承是仅ơ于友元的第二紧密的耦合关系
软g工程中的一条明智原则就是,量减少耦合
通过Q智能)指针保存对象Q可以减头文g依赖?br />Pimpl技术:所有私有成员聚合在一个不透明的指针后?br />必须使用l承的情况:
1 需要改写虚拟函?br />2 需要访问保护成?br />3 需要在基类前构造已使用q的对象Q或者在基类之后销毁此对象Q基cL子类先构造,后析构)
4 需要操心虚拟基c?br />
Q?5 避免从非必要设计成基cȝcMl承
独立cd基类的设计有不同的考虑
Q?6 优先提供抽象接口
优先采用实现了抽象接口的设计层次l构
Q?7 公用l承卛_替换性。承,不是Z重用Q而是Z被重?br />公用l承描述的是“is-a”或者“works like a”关p?br />l合描述的是“用...来实现”关p?br />
Q?8 实施安全的改?br />
Q?9 考虑虚拟函数声明ؓ非公用的Q将公用函数声明为非虚拟?br />
Q?0 避免提供隐式转换
隐式转换构造函敎ͼ能够用一个参数调用且未声明ؓexplicit的构造函数?br />
Q?1 数据成员设为私有的、无行ؓ的聚?br />
Q?2 不要公开内部数据
Q?3 明智C用Pimpl
实现~译器防火墙
class A
{
private:
struct Impl;//存储所有私有成?br />shared_ptr<Impl> pimpl_;
}
Q?4 优先~写非成员非友元函数
Q?5 L一h供new和delete
Q?6 如果提供cM门的newQ应该提供所有标准Ş式(普通、就地和不抛出)
void* operator new(std::size_t);//普?br />void* operator new(std::size_t,std::nothrow_t) throw();//不抛?br />void* operator new(std::size_t,void*);
定义了一个某UŞ式的重蝲会隐藏其他的重蝲形式
构造、析构与复制
Q?7 以同L序定义和初始化成员变量
成员变量初始化顺序与在类中声明的序一?br />
Q?8 在构造函C用初始化代替赋?br />
Q?9 避免在构造函数和析构函数中调用虚拟函?br />虚拟函数在构造函数和析构函数中ƈ不虚?br />
Q?0 基cL构函数设为公用且虚拟的,或者保护且非虚拟的
Q?1 析构函数、释攑֒交换l对不能p|
Q?2 一致地q行复制和销?br />同时定义复制构造函敎ͼ复制赋值操作符和析构函?br />
Q?3 昑ּ地启用或止复制
Q?4 避免切片Q在基类中考虑用克隆代替复?br />
Q?5 使用赋值的标准形式
Q?6 只要可行Q就提供不会p|的swap
名字I间与模?/span>
模块Q同一个h或小l维护的紧凑的发布单?br />Q?7 类型及光成员函数接口|于同一名字I间?br />对于一个类X而言Q所有在同一个名字空间中提及X和随X一h供的函数逻辑上都是X的一部分Q它们Ş成了X接口的组成部分?br />ADL 参数依赖查找
Q?8 应该类型和函数分别|于不同的名字空间中Q除非有意想让它们一起工?br />
Q?9 不要在头文g中或者#include之前~写名字I间using
在头文g中不要用using指o或声明,而应该显CZ用名字空间限定所有名?br />不要在#include之前使用using
Q?0 避免在不同的模块中分配和释放内存
Q?1 不要在头文g中定义具有链接的实体
Q?2 不要允许异常跨越模块边界传播
Q?3 在模块的接口中用具有良好可U至性的cd
不要让类型出现在波快的外部接口中Q除非能保所有的客户代码都能够正地理解该类型?br />使用客户代码能够理解的最高层抽象?br />抽象层越低,可移x越好?br />
模板与泛?/span>
Q?4 理智地结合静态多态性和动态多态?br />静态多态性是指模板类和模块函?br />动态多态性是指类的虚拟函数和间接引用
Q?5 有意地进行显C定义
Q?6 不要特化函数模板
Q?7 不要无意地编写不通用的代?
错误处理与异?
问题不在与我们是否会犯错误,而在于我们是否会安排~译器和工具L错误?br />
Q?8 q泛C用断a记录内部假设和不变式
一个事件中所含的信息量与该事件发生的概率是成反比的?br />不要使用断言报告q行旉?br />
Q?9 建立合理的错误处理策略,q严格遵?br />只在模块边界处改变错误处理机?br />
Q?0 区别错误与非错误
前条?br />后条?br />不变?br />
Q?1 设计和编写错误安全代?br />基本保证Q确保出现错误时E序会处于有效状态?br />Z证:保证最l状态要么时最初状态,要么是所希望的目标状态?br />不会p|保证Q保证操作永q不会失败?br />
Q?2 优先使用异常报告错误
使用异常而不是错误码
Q?3 通过值抛出,通过引用捕获
Q?4 正确地报告、处理和转换错误
Q?5 避免使用异常规范
STL容器
Q?6 默认使用vectorQ否则,选择其他合适的容器
Q?7 用vector和string代替数组
Q?8 使用vector与非C++API交换数据
&*iter:获取q代器引用元素的地址
Q?9 在容器中只存储值和指针
在容器中存储值对?br />
Q?0 用push_back代替其他扩展序列的方?br />push_back 是按指数U扩大容量的
Q?1 多用范围操作Q少用单元素操作
Q?2 使用公认的惯用法真正地压~容量,真正地删除元?br />swapQ?br />container<T>(c).swap(c);//去除多余定w的shrink-to-fit惯用?br />container<T>().swap(c);//去除全部内容和容量的惯用?br />c.erase(remove(c.begin(),c.end(),value),c.end());//删除元素的惯用法
STL法
多用法Q少用@?br />Q?3 使用带检查的STL实现
Q?4 用算法调用代替手工编写的循环
采取“处理此范围”的法性思维方式Q取代“处理每个元素”的循环式思\
使用boost.lambda?br />
Q?5 使用正确的STL查找法
查找无序范围Qfind/find_if
查找有序范围Qlow_bound, upper_bound, equal_range, binary_search.
Ҏ序范_p=equal_range(first,last,value);distance(p.first,p.end);比count(first,last,value);更快
Q?6 使用正确的STL排序法
开销从低到高Qpartition,stable_partition,nth_element, partial_sort(partial_sort_copy),sort,stable_sort
Q?7 使谓词成为纯函数
谓词类型的operator()声明为const
Q?8 法和比较器的参数应多用函数对象用函数
Q?9 正确~写函数对象
函数对象设计ؓ复制成本很低的值类型。尽可能从unary_function或binary_functionl承
cd安全
Q?0 避免使用cd分支Q多使用多?br />
Q?1 依赖cdQ而非其表C方?br />
Q?2 避免使用reinterpret_cast
Q?3 避免Ҏ针用static_cast
使用dynamic_cast
Q?4 避免强制转换const
Q?5 不要使用C风格的强制{?br />
Q?6 不要寚wPODq行memcpy或者memcmp操作
Q?7 不要使用联合重现解释表达方式
Q?8 不要使用可变长参?br />boost.format?br />
Q?9 不要使用失效对象。不要用不安全函数
不要使用不安全的C语言遗留函数
Q?00 不要多态地处理数组
基类对象的数l和子类对象的数l是完全不同的类?

]]>