首页 > 代码库 > 编写高质量代码——“零星”总结(续3)

编写高质量代码——“零星”总结(续3)

明白在C++中如何使用C

C++中使用C的程序库,实现C++和C的混合编程:extern "C" { /* code */ }一定要加在C++的代码文件中才能起作用。

//C编译器编译函数时不带函数的类型信息,只包含函数符号名字;而C++编译器为了实现函数重载,在编译时会带上函数的类型信息。extern "C"的作用:告诉C++链接器寻找调用函数的符号时,采用C的方式。

===================================

使用memcpy()系列函数时要足够小心【memcpy()、memset()、memcmp()】

在C语言中,无论是内置类型,还是自定义的结构类型(struct),其内存模型都是可知的,透明的,故可以对该对象的底层字节序列一一进行操作。

在C++中,把C 中的数据类型叫做POD(Plain Old Data)对象(C的所有对象都是POD)。POD对象特性:二进制内容是可以随意复制的。

C++标准并未对非POD对象的内存布局做任何定义,对于不同的编译器,其对象布局是不同的。而在C语言中,对象布局仅仅会受到底层硬件系统差异的影响。

===================================

尽量用new/delete 代替malloc/free

malloc与new之间的主要区别:

1)new 是C++ 运算符,而malloc 则是C标准库函数。

2)通过new创建的东西是具有类型的,而malloc函数返回的则是void*,需要进行强制转型。

3)new 可以自动调用的构造函数,而malloc不会。

4)new 失败时会调用 new_handler 处理函数,而malloc失败则之间返回 NULL。

------------------------------------

free与delete之间的只有两点区别:

1)delete 是C++运算符,free 是C标准库函数。

2)delete 可以自动调用对象的析构函数,而malloc 不会。

针对内置函数,没有对象的构造与析构,故malloc/free 除了需要强制转型之外,和new/delete无异。

realloc(C中重新设置内存块的大小):C++中只能先释放原来的内存,再重新申请。

===================================

尽量使用C++标准的 iostream

1)prinf缺点:《尽量不要使用可变参数》;而C++ iostream 类型安全,可扩充性强。

2)C中的stream优点:

a.一般认为C stream函数生成的可执行文件更小,效率更高。

b.C++ stream 程序库中的类会涉及对象构造、析构的问题。而 C stream 函数没有。

c.C stream 函数有更强的可移植能力。

===================================

尽量采用C++风格的强制类型转型

链接:reintepret_cast、static_cast、dynamic_cast、const_cast

C++强制转型更安全、转型针对性更强。

===================================

尽量用const、enum、inline替换#define<尽量把工作交给编译器而非预处理器>

#define PI 3.1415926       //#define不属于语言自身范畴、PI符号名不会被编译器列入符号表

const double PI  = 3.1415926;//常量属于语言层面、PI会进入符号表、常量可以避免目标码的多份复制,即生成的目标代码更小。因为预处理器会替换目标代码中所有宏PI,而常量只会分配一块内存

-----------------------------------

定义常量的数据成员的主要目的是为了将常量的作用域限制在一个特定的类里,为了让限制常量最多只有一份,还必须将该常量用static进行修饰:

static const int NUM_LESSONS = 5;//声明唯一常量(类内初始化)(一般形式的初始化不允许放在声明里,需将其初始化放到实现文件中,该变量的定义处:const double CMath::PI = 3.1415926;/*实现文件.cpp */)

早期的编译器可能不接受在声明一个静态的类成员时为其赋初值。

-----------------------------------

如果编译器不支持类内初始化,而此时编译器又恰恰需要定义的成员常量值,借助enum 解决,枚举类型可以冒充整数给程序使用。

class CStudent{

private:

  enum{ NUM_LESSONS = 5 };

  int scores[ NUM_LESSONS];  }; 

-----------------------------------

类内部的静态常量绝对不能使用#define来创建,#define的世界中没有域的概念,即没有任何封装效果。

-----------------------------------

C++的inline内联函数:对于形似函数的宏,尽量使用内联函数,既可以得到宏的高效,又可以保证类型的安全。

===================================

用引用代替指针

引用只是其对应实体的别名,能对引用做的唯一操作是将其初始化(必须在定义时就初始化)。一旦初始化结束,引用就是其对应实体的另一种叫法了。不占用任何存储空间,由于没有地址,因此不存在引用的引用、指向应用的指针或引用的数组等定义。