C++ Keywords
const
- 避免无意中修改数据。
- 能够处理 const 和非 const 实参,否则只能接收非 const 数据。
- 使函数能够正确生成并使用临时变量。
const 是 constant 的缩写,“恒定不变”的意思。被 const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多 C++ 程序设计书籍建议:“Use const whenever you need”。s
如果参数作输出用,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加 const 修饰,否则该参数将失去输出功能。const 只能修饰输入参数,如果输入参数采用“指针传递”,那么加 const 修饰可以防止意外地改动该指针,起到保护作用。
函数返回值不可作为左值。在“指针传递”和“引用传递”时可以加
const
修饰,但是在“值传递”的情况下,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const
修饰。1
2
3const int *fun(int *xxx) {}
const int &fun(int &xxx) {}
int fun(int xxx) {}形参在本函数内不能作为左值。
1
2
3int *fun(const int *xxx) {}
int &fun(const int &xxx) {}
int fun(const int xxx) {}任何不会修改数据成员的函数都应该声明为 const 类型。此种写法表示本函数不会修改本对象中的成员变量。
1
int* fun(int* xxx) const {}
extern
- 单定义规则
- 变量只能被定义一次;
- 定义声明(defining declaration,简称定义);
- 引用声明(referencing declaration,简称声明);
- 一个变量多处使用,仅在其中一个文件中包含定义,在使用该变量的其它文件中使用该关键字声明
static
隐藏,保持内容持久,默认初始化为 0
- 静态全局变量,全局生命周期,本文件可见。
- 静态局部变量,全局生命周期,仅局部可见。
- 静态函数,全局生命周期,全局可见。
- 静态成员变量,全局生命周期,同类对象共享一份。
- 静态成员函数,全局生命周期,同类对象共享一份。
1 |
|
inline
内联函数是函数,有类型检查,语法判断等,在编译时展开,嵌入代码中。
宏定义在预编译阶段展开,只是简单的文本替换。
virtual
虚函数是为了实现多态,析构函数是为了在对象不被使用之后释放它的资源。
那么把析构函数声明为 virtual 有什么作用呢?
直接的讲,C++ 中基类采用 virtual 虚析构函数是为了防止内存泄漏。
具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,基类的析构函数应采用 virtual 虚析构函数。对象在析构时,先调用派生类的析构函数后,再调用基类的析构函数,从而保证所有申请的资源都被释放。
explicit
- 指定构造函数或转换函数 (C++11 起)或推导指引 (C++17 起)为显式,即它不能用于隐式转换和复制初始化。
- explicit 说明符可以与常量表达式一同使用。函数在且只会在该常量表达式求值为 true 时是显式的。(C++20 起)
decltype
推导表达式类型:
1 |
|
与using
和typedef
配合使用,用于定义类型:
1 |
|
重用匿名类型:
1 |
|
泛型编程中结合 auto,用于追踪函数的返回值类型:
1 |
|
template
函数模板,类模板。
特化与偏特化:模板特殊化和部分特殊化。
- 函数模板只有特化,没有偏特化;
- 模板、模板的特化和模板的偏特化都存在的情况下,编译器在编译阶段进行匹配,优先特殊的;
- 模板函数不能是虚函数;因为每个包含虚函数的类具有一个 virtual table,包含该类的所有虚函数的地址,因此 vtable 的大小是确定的。模板只有被使用时才会被实例化,将其声明为虚函数会使 vtable 的大小不确定。所以,成员函数模板不能为虚函数。