C++ 99 个常见错误 一

来源:互联网 发布:西安二手房增值税算法 编辑:程序博客网 时间:2024/05/07 08:59

A.基础问题

1.过分注释(对注释的更新与代码不一致), 字面常量(幻数,看不出意义, 可用 enum 或 const 解决).

2.全局变量.  

    <--幼稚的消息传递机制

    (1) 可用函数调用得到 (2) 可用一个类单例得到

3.未能区分函数重载和形参默认值.

4.引用

   引用只是其初始化物的别名.引用是没有地址的,甚至不占有任何存储空间. 由于无地址,声明指向引用的指针,引用的引用都是不合法的。

    注:没有空引用,也无类型为void的引用。任何可作为左值的都可被引用 .

    指向数组的引用 : int ( & array )[10] ;     <=保留了尺寸

    int f(double) ;     f(18.6) <=> (*f)(18.6)

5.对常量的误区:

    const <- 常量,  10 <- 字面量

    const volatile <= 只限制对const 的直接修改,间接修改是可行的,不会引发未定义的行为(??)

6.无视语言的精妙之处:

    (1) bool r = a < b ;       <=  never use if in this case !!! 不要用 if

    (2) 位屏蔽算法:      b & m & ((b & m) - 1)      ;;结果为0则没选或只选一个

    (3) 如果条件运算符表达式两个选择结果都为左值,那么这个表达式就是左值 :

            a<b ? c: d < e ? d: e = val();

    (4) 内建索引运算符 :

          p[-2]  <=>  *(p + (-2))  <=> * ( -2 + p)  <=>  (-2)[p]

    (5) switch  <= 只管入口,如果要直下,最好加上注释.

         另:case 可不在同一级,case 可在任何地方.

7.空指针: #define NULL ((char * )0)  / ((void*)0)  / 0

       故,最好用 0 : C * cp = 0;

8.无视习惯用法:

   X ( const X &) ;      X & operator = ( const X &)

 

 

 

语法问题:

1. int * ip = new int(12) ;     //仅初始化了一个整数,并非一个数组

    int a[12] ; int a(12); 

    vector <int> iv(12);         <--下标访问,不用显式回收

    注:最好的内存申请形式就是根本不做这个内存申请,直接用标准库中组件.

2. 不定的求值顺序:

    (a=12) + a

    a=( p() + q() ) + r();

    <---可以有六种顺序

    Thing * pThing = new ( Thing ( initVal() ) ;

    <---可以肯定 operator new 会比 Thing 类型构造函数先调用(先分配空间,后初始化.)

     return  f(), g(), h();

     a = f() + g() ? p() : q(); <=> a = ( f() + g() ) ? p() : q();

     左结合性:该运算符先会绑定左边那个参数;

     -> 有很高的优先级, 但是低于 ()

     ++ 高于 -> *

3. for 语句 

   if ( char * theName = lookUp( name )){ /*****/ }

   for ( int i = 0 ; ; ){     }

4. 取大优先: list < vector < string >> lovos;    //  >>之间要有空格!!,不然会被当作...

5.声明饰词:  先连接,再量化,最后类型

   int const * const * pp1;    extern const int;

6. 是函数还是对象: String x(); <-函数声明,多义    String x(void)

    String * sp1 = new String () ; <=> sp1 = m new String; (后面较好)

7.自反初始化:

   int var = 12;

   {

    double var = var;  // 未定义...        对枚举则可行

    }   

8. 运算符名字查找的反常行为:

    中序语法调用:

    函数调用语法: 名字查找遵从标准形式

9 operator -> : 重载版本是一元的,并且它必须返回一个可用 -> 访问其成员的对象.

 

 

 

预处理问题:

1. #define 的作用域并未被限制在名字空间中;

    尽量不要用 #define 调用的伪函数. ---> static const ,函数对象,operator()

2. 如果调试代码在最终生成的可执行文件中根本不存在,那么编译器会剔除无用代码...

    if( false ) { /******/ }

    避免用 #if 作为源代码的控制.

3. assert 是一个宏 <--- 即也是一个伪函数.   #define assert(e) ((void) 0)

    ----->所以,当使用 assert 时,不要在 e 中使用函数调用.

  

 

 

原创粉丝点击