【笔记】C++的150个建议,第二章

目录
第一部分 语法篇

  1. 第一章 从C继承而来
  2. 第二章 从C到C++
  3. 第三章 内存管理
  4. 第四章 类

第2章 从C到C++

建议19:在C++中使用C

C++虽然兼容绝大部分C的语法,但是还是有些不兼容。比如,C允许从void类型指针隐式转换成其他类型的指针,但是C++禁止此行为。

// 从void* 隐式转换成double*
double* p = malloc(nCount * sizeof(double))

在C++中调用C代码的几种方式:

// 1.在原函数声明前添加
extern "C" int Function(void);
// 2.在调用函数的C++代码中重新声明一下C函数
extern "C" int Function(void);
// 3.在包含C头文件时添加
extern "C" {
    #include "CDemo.h"
}

建议20:小心memcpy、memset、memcmp等内存操作函数

C语言的数据类型叫做POD对象(Plain Old Data)。POD对象的二进制内容是可以随意复制的,在内存中是连续的,能通过对象的基地址和数据成员的偏移量获取数据成员的地址。所以可以使用这些内存操作函数操作POD对象。

但是,C++中的对象可能不是POD,因为多态会用到虚函数表,对象的数据体中不仅有数据成员,还有虚函数表。对象的数据成员在内存中是不连续的。

建议21:用new/delete代替malloc/free

  • new/delete,运算符。会调用构造函数和析构函数。
  • malloc/free,库函数。仅实现内存的分配和释放。
  • 通过new创建的东西具有类型,而malloc函数返回的是void*,使用时需要进行强制转换
  • new失败时会调用new_handler处理函数,而malloc失败则返回NULL
  • delete可以自动调用对象的析构函数,而malloc不会

建议22:灵活使用不同风格的注释

  • 版权声明用C风格的/**/
  • 注释嵌套时,内嵌的注释用//
  • 宏尾端的注释用/**/

一种特殊情形:默认参数函数的定义。
在实现文件中添加C风格的注释,使程序更加清晰易懂。

// 声明文件
class A
{
public:
    void Function(int para1, int para2 = 0);
};
// 实现文件
void A::Function(int para1, int para2 /* = 0 */)
{
}

建议23:尽量使用C++标准的iostream

几类头文件

  1. "stdio.h",标准化以前C++中的C标准库
  2. "cstdio.h",标准化后经过改造的C标准库,用std包装,例如std::printf()
  3. "iostream.h",没有用std包装的C++"准"标准库
  4. "iostream",用std包装的C++标准库,首选

建议24:尽量使用C++风格的强制转型

C++风格的强制变换更安全,参考建议11

建议25:尽量使用const、enum、inline替换#define

从源代码到二进制文件的过程:预处理->编译->链接。宏替换在预处理阶段。
尽量将工作交给编译器,而不是预处理器。

  1. 用内联函数替换宏定义函数,既可以得到宏的高效,又能保证类型安全
template 
inline T Add(const T&a, const T& b)
{
    return (a+b);
}
  1. 常量指针与指向常量的指针:如果const出现在*左边,则数据为常量;如果在*右边,则指针为常量。
const int * p = 123;        // 指向常量的指针
int * const p = 123;        // 常指针
const int * const p = 123;  // 指向常量的长指针

建议26:用引用代替指针

引用只是对应实体的别名,引用必须初始化。
引用不占任何存储空间,因此不存在引用的引用、指向引用的指针(实质上是指向被引用实体的指针)、引用的数组。

你可能感兴趣的:(【笔记】C++的150个建议,第二章)