C++编程规范 读书笔记(下)

来源:互联网 发布:sql with语句 编辑:程序博客网 时间:2024/05/01 22:52

《C++编程规范——101条规则、准则与最佳实践》(C++ Coding Standards——101 Rules, Guidelines and Best Practices)

名字空间与模块

第57条(D):将类型及其非成员函数接口置于同一名字空间中

第58条(D):应该将类型和函数分别置于不同的名字空间中,除非有意想让他们一起工作

       ADL(参数依赖查找,也成Koeing查找)。

      关于57条和58条,在机器上实验了一下,没发现啥问题呀。???

第59条(A):不要在头文件中或者#include之前编写名字空间using

       名字空间 using 是为了使我们更方便,而不是让我们用来叨扰别人的:在 #include 之前,绝对不要编写 using 声明或者 using 指令。
       推论:在头文件中,不要编写名字空间级的 using 指令或者 using 声明,相反应该显式地用名字空间限定所有的名字。(第二条规则是从第一条直接得出的,因为头文件无法知道以后其他头文件会出现什么样的 #include 。) 简而言之:可以而且应该在实现文件中的 #include 指令之后自由地使用名字空间级的 using 声明和指令,而且会感觉良好。
第60条(D):要避免在不同的模块中分配和释放内存

第61条(A):不要在头文件中定义具有链接的实体

[cpp] view plaincopy
  1. // 不要在头文件中定义具有外部链接的实体  
  2. int fudgeFactor;  
  3. std::string hello("hi, lcz");  
  4. void foo() { std::cout << "lcz" << std::endl; }  


而解决方法也很简单,应该像如下只在头文件中声明:

[cpp] view plaincopy
  1. extern int fudgeFactor;  
  2. extern std::string hello;  
  3. void foo(); // extern 对函数的声明是可有可无的  


在实现文件中定义:

[cpp] view plaincopy
  1. int fudgeFactor;  
  2. std::string hello("hi, lcz");  
  3. void foo() { std::cout << "lcz" << std::endl; }  


同样的,以下在头文件中定义名字空间级的static实体是更危险的行为(因为链接器通常不会报错):

[cpp] view plaincopy
  1. static int fudgeFactor;  
  2. static std::string hello("hi, lcz");  
  3. static void foo() { std::cout << "lcz" << std::endl; }  


第62条:不要允许异常跨越模块边界传播

第63条(D):在模块的接口中使用具有良好可移植性的类型

错误处理与异常

第68条(B):广泛地使用断言记录内部假设和不变式

     断言的强大怎么高估都不算过分。1)按照信息论的原理,一个事件中所包含的信息量与该事件发生的概率是成反比的。因此,如果assert触发的可能性越低,它触发时所提供的信息量就越大。2)避免使用assert(false),应该使用assert( !"information message" ); // 这样有一个很有用的好处,可以取代注释。3)断言是用来报告程序员的错误的,因此,不要使用断言报告运行时的错误。

第69条:建立合理的错误处理策略,并严格遵守

第70条:区别错误与非错误

第71条:设计和编写错误安全代码

第72条:优先使用异常报告错误

第73条:通过值抛出,通过引用捕获

第74条:正确地报告、处理和转换错误

第75条:避免使用异常规范

    错误处理与异常这一块在项目中实践得很肤浅,没有什么心得与体会。一般都是遇到错误了即返回,抛出错误日志。

类型安全

第90条(C):避免使用类型分支,多使用多态

第91条(C):依赖类型,而非其表示方式

第92条(A):避免使用reinterpret_cast

     如果需要在不相关的指针类型之间强制转换,应该通过void进行转换,不要直接使用reinterpret_cast.

例如:

[cpp] view plaincopy
  1. T1 *p1 = ...  
  2. T2 *p2 = reinterpret<T2*>(p1); // 糟糕!   


应该写成:

[cpp] view plaincopy
  1. T1 *p1 = ....  
  2. void *p = p1; // 先用void*指向p1指向的内存区  
  3. T2 *p2 = static_cast<T2>(p);    


第93条(A):避免对指针使用static_cast

第94条(A):避免强制转换const(const_cast)

第95条(D):不要使用C风格的强制转换

第96条(D):不要对非POD进行 memcpy 和 memcmp 操作

第97条(C):不要使用联合(union)重新解释表示方式

     有两种方式是可以接受的:1)读取最后写入的字段(在一些接口需要统一参数而实际参数类型又不相同的时候,经常使用这一招);2)如果两个POD是一union的成员,而且均以相同的字段类型开始,那么对这种匹配的字段来说,写入其中一个而读取另一个是合法的。

第98条(A):不要使用可变长参数(...)

     就算要用,我也不会编写。呵呵

第99条(B):不要使用失效对象。不要使用不安全函数

    不要使用不安全的C语言遗留函数:strcpy, strncpy, sprintf等C函数。

第100条(B):不要多态地处理数组

    1)避免使用数组,而应该使用vector; 2)不要在数组或vector中存储多态的值对象,而应该存储对象指针(最好是智能指针)。

0 0
原创粉丝点击