C++语言学习坚持百日基本功-标识符体系-4
我们来系统地梳理一下 C++ 中的标识符和关键字。
这份指南将分为以下几个主要部分:
1. **C++ 标识符 (Identifiers)**:详细解释标识符的定义、命名规则、分类和最佳实践。
2. **C++ 关键字 (Keywords)**:提供完整的关键字列表,并按功能分组详细解释,包括 C++11 及以后版本新增的关键字。
3. **C++ 操作符关键字 (Operator Keywords)**:介绍那些看起来像操作符但实际上是关键字的特殊符号。
4. **C++ 预处理器指令 (Preprocessor Directives)**:虽然它们不是严格意义上的关键字,但在语法上类似,用于控制编译过程。
---
## 第一部分:C++ 标识符 (Identifiers)
### 1.1 什么是标识符?
**标识符**是用来命名程序中实体的名称,例如变量、函数、类、结构体、枚举、命名空间、模板等。简单来说,标识符就是程序员为程序中的各种“东西”起的名字。
例如,在代码 `int student_age = 20;` 中,`student_age` 就是一个标识符,它命名了一个整型变量。
### 1.2 标识符的命名规则
C++ 对标识符的命名有严格的规则,违反这些规则会导致编译错误:
1. **字符构成**:
* 只能由字母(`a-z`, `A-Z`)、数字(`0-9`)和下划线(`_`)组成。
* **第一个字符必须是字母或下划线**,不能是数字。
* C++11 及以后支持 Unicode 字符,但通常不推荐在跨平台或多人协作项目中使用,以避免编码问题。
2. **大小写敏感**:C++ 是大小写敏感的语言。这意味着 `age`、`Age` 和 `AGE` 是三个完全不同的标识符。
```cpp
int age = 10;
int Age = 20;
int AGE = 30;
// 这三个变量都是独立的
```
3. **关键字冲突**:**不能**使用 C++ 的关键字(如 `int`, `class`, `if`, `for`)作为标识符。
```cpp
int int = 5; // 错误!'int' 是关键字
```
4. **长度限制**:C++ 标准没有规定标识符的最大长度,但编译器通常有一个实际的限制(例如,GCC 早期版本限制为 31 个字符,现在已大大增加)。为了代码的可读性和可移植性,建议保持标识符长度适中。
### 1.3 标识符的分类
根据其在程序中的作用,标识符可以分为以下几类:
* **变量名**:用于命名变量(`int count;`, `std::string name;`)。
* **函数名**:用于命名函数(`void print_report();`, `int calculate_sum(int a, int b);`)。
* **类名**:用于命名类(`class Student {};`)。
* **结构体名**:用于命名结构体(`struct Point {};`)。
* **枚举名和枚举值**:用于命名枚举类型和其成员(`enum Color { RED, GREEN };`)。
* **命名空间名**:用于命名命名空间(`namespace MyApp {};`)。
* **模板名**:用于命名模板(`template <typename T> class List {};`)。
* **常量名**:用于命名常量(`const double PI = 3.14159;`)。
* **类型别名**:用于命名类型的别名(`typedef unsigned int uint;`, `using String = std::string;`)。
### 1.4 标识符命名规范(Best Practices)
好的命名规范对于代码的可读性和可维护性至关重要。以下是一些被广泛接受的 C++ 命名规范:
1. **清晰、有意义**:标识符应能清晰地表达其用途或含义,避免使用无意义的单字母(除非是广为人知的约定,如 `i` 用于循环索引,`x`, `y` 用于坐标)。
* **不好**:`int x;`, `void f();`
* **好**:`int user_count;`, `void generate_report();`
2. **一致性**:在整个项目中坚持使用同一种命名风格。
3. **常用命名风格**:
* **驼峰命名法 (camelCase)**:首字母小写,后续每个单词的首字母大写。常用于变量名和函数名。
* 示例:`studentAge`, `calculateTotalScore()`
* **帕斯卡命名法 (PascalCase)**:每个单词的首字母都大写。常用于类名、结构体名、枚举名和命名空间名。
* 示例:`StudentRecord`, `ColorScheme`, `MathUtils`
* **下划线命名法 (snake_case)**:单词之间用下划线分隔。在 C++ 社区中也非常流行,尤其在标准库和一些大型项目中。
* 示例:`student_age`, `calculate_total_score()`, `MAX_BUFFER_SIZE`
* **匈牙利命名法 (Hungarian Notation)**:在变量名前加上表示其类型的前缀(如 `i` 表示 `int`,`str` 表示 `string`)。这种风格在老的 Windows 编程中很常见,但现在已不被推荐,因为它会使代码冗长,且现代 IDE 能很好地显示变量类型。
* 示例:`int iStudentCount;`, `std::string strName;`
4. **常量和宏**:通常使用全大写的下划线命名法。
* 示例:`const int MAX_STUDENTS = 50;`, `#define PI 3.14159`
5. **避免使用下划线开头**:以下划线开头的标识符(尤其是双下划线 `__` 或下划线后跟大写字母)通常被编译器和标准库内部使用。为了避免命名冲突,用户代码应避免使用。
```cpp
int _internal_variable; // 不推荐
int __private_data; // 强烈不推荐,可能与库冲突
```
## 第二部分:C++ 关键字 (Keywords)
**关键字**是 C++ 语言本身预先定义好的、具有特殊含义的单词。它们不能被用作标识符。
C++ 的关键字分为几类,我们将逐一介绍。
### 2.1 按功能分组的关键字列表
#### 2.1.1 基本数据类型和类型修饰符
这些关键字用于声明变量和函数的类型。
* `bool`: 布尔类型(`true` 或 `false`)。
* `char`: 字符类型。
* `char8_t`: (C++20) 无符号 8 位字符类型,用于 UTF-8。
* `char16_t`: (C++11) 无符号 16 位字符类型,用于 UTF-16。
* `char32_t`: (C++11) 无符号 32 位字符类型,用于 UTF-32。
* `wchar_t`: 宽字符类型,用于存储超出 ASCII 范围的字符。
* `short`: 短整型。
* `int`: 整型。
* `long`: 长整型。
* `long long`: (C++11) 更长的整型。
* `float`: 单精度浮点型。
* `double`: 双精度浮点型。
* `void`: 表示“无类型”,用于函数返回类型或指针类型。
* `signed`: 有符号修饰符,表示变量可以存储正数、负数和零。
* `unsigned`: 无符号修饰符,表示变量只能存储非负数。
**示例**:
```cpp
int x = 10;
unsigned int y = 20U;
double pi = 3.14159;
char initial = 'A';
bool is_valid = true;
void print_hello() { std::cout << "Hello"; }
```
#### 2.1.2 控制流语句
这些关键字用于控制程序的执行流程。
* `if`: 条件判断。
* `else`: 与 `if` 配合,处理不满足条件的情况。
* `else if`: (C++17 作为关键字) 嵌套的条件判断。
* `switch`: 多分支选择语句。
* `case`: `switch` 语句中的分支标签。
* `default`: `switch` 语句中没有匹配 `case` 时的默认分支。
* `break`: 跳出当前循环或 `switch` 语句。
* `for`: 循环语句。
* `while`: 循环语句。
* `do`: 与 `while` 配合,构成 do-while 循环。
* `goto`: 无条件跳转语句(不推荐使用,会破坏代码结构)。
* `continue`: 跳过循环体中剩余的语句,直接进入下一次循环。
* `return`: 从函数中返回,可以带返回值。
**示例**:
```cpp
int score = 85;
if (score > 90) {
std::cout << "Excellent";
} else if (score > 70) {
std::cout << "Good";
} else {
std::cout << "Needs improvement";
}
for (int i = 0; i < 10; ++i) {
if (i % 2 == 0) continue; // 跳过偶数
std::cout << i << " ";
}
```
#### 2.1.3 复合类型和数据结构
* `class`: 定义一个类。
* `struct`: 定义一个结构体。
* `enum`: 定义一个枚举类型。
* `enum class`: (C++11) 定义一个强类型枚举(作用域枚举),可以避免枚举值之间的命名冲突。
* `union`: 定义一个联合体,所有成员共享同一块内存。
* `typedef`: 为现有类型创建一个新的名字(类型别名)。
* `using`: (C++11) 用于类型别名(`using MyInt = int;`)和引入命名空间或类成员(`using namespace std;`)。
**示例**:
```cpp
struct Point {
int x;
int y;
};
enum class Color { Red, Green, Blue };
Color c = Color::Green;
typedef std::map<std::string, int> StringToIntMap;
using StringToIntMap = std::map<std::string, int>; // C++11 类型别名
```
#### 2.1.4 访问控制和继承
这些关键字用于类定义中,控制成员的访问权限和继承方式。
* `public`: 公有成员,在任何地方都可以访问。
* `private`: 私有成员,只能在类的内部访问。
* `protected`: 保护成员,只能在类的内部或其子类中访问。
* `friend`: 声明一个函数或另一个类为友元,可以访问本类的私有和保护成员。
* `virtual`: 声明一个虚函数,支持多态。
* `override`: (C++11) 显式声明一个函数重写了基类中的虚函数,有助于编译器检查。
* `final`: (C++11) 用于防止类被继承或虚函数被进一步重写。
* `static`: 静态存储说明符。
* 对于变量:生存期贯穿整个程序,作用域在所在的编译单元。
* 对于类成员:属于类本身,而不是类的某个实例。
* 对于函数:作用域在所在的编译单元。
* `register`: 提示编译器将变量存储在寄存器中(现代编译器优化器通常会忽略此提示)。
* `mutable`: 允许在 `const` 成员函数中修改被修饰的类成员。
**示例**:
```cpp
class Base {
public:
virtual void show() { std::cout << "Base"; }
};
class Derived : public Base {
public:
void show() override { std::cout << "Derived"; } // 重写基类虚函数
};
class FinalClass final { /* ... */ }; // 此类不能被继承
```
#### 2.1.5 内存管理
* `new`: 动态分配内存,并调用对象的构造函数。
* `delete`: 释放由 `new` 分配的内存,并调用对象的析构函数。
* `new[]`: 动态分配数组内存。
* `delete[]`: 释放由 `new[]` 分配的数组内存。
* `sizeof`: 运算符,返回一个类型或变量所占的字节数。
* `alignof`: (C++11) 运算符,返回一个类型的对齐要求。
* `decltype`: (C++11) 推断一个表达式的类型。
**示例**:
```cpp
int* p = new int(10);
delete p;
int* arr = new int[5];
delete[] arr;
std::cout << sizeof(int) << std::endl; // 输出 4 (在32/64位系统上通常如此)
```
#### 2.1.6 模板和泛型编程
* `template`: 用于定义函数模板或类模板。
* `typename`: 在模板参数列表中,用于指定一个类型参数。在某些上下文中可以与 `class` 互换,但 `typename` 更明确。
* `class`: 也可用于模板参数列表。
* `constexpr`: (C++11) 用于声明可以在编译时计算的常量表达式或函数。
* `consteval`: (C++20) 强制函数在编译时求值,比 `constexpr` 更强。
* `const_cast`: 类型转换运算符,用于移除 `const` 或 `volatile` 限定符。
* `static_cast`: 静态类型转换,用于相关类型之间的转换。
* `dynamic_cast`: 动态类型转换,用于在继承层次中安全地向下转换,需要虚函数支持。
* `reinterpret_cast`: 重新解释类型转换,最底层的转换,风险最高。
**示例**:
```cpp
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
constexpr int factorial(int n) {
return n <= 1 ? 1 : (n * factorial(n - 1));
}
int arr[factorial(5)]; // 编译时计算数组大小
```
#### 2.1.7 异常处理
* `try`: 定义一个可能抛出异常的代码块。
* `catch`: 捕获并处理 `try` 块中抛出的异常。
* `throw`: 抛出一个异常。
* `noexcept`: (C++11) 用于指定函数不会抛出任何异常,有助于编译器优化。
**示例**:
```cpp
try {
int x = 10;
int y = 0;
if (y == 0) {
throw std::runtime_error("Division by zero");
}
int z = x / y;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
```
#### 2.1.8 其他关键字
* `namespace`: 定义一个命名空间,用于组织代码,避免命名冲突。
* `using`:
* `using namespace std;` // 引入整个命名空间
* `using std::cout;` // 引入命名空间中的特定成员
* `using MyType = int;` // 类型别名 (C++11)
* `this`: 指针,在类的非静态成员函数中,指向调用该函数的对象。
* `const`: 限定符,表示一个变量的值不能被修改,或一个成员函数不会修改对象的状态。
* `volatile`: 限定符,告诉编译器变量的值可能在任何时候被外部因素(如硬件中断)改变,因此每次使用时都必须从内存中重新读取,禁止某些优化。
* `asm`: 允许在 C++ 代码中嵌入汇编语言指令。
* `auto`: (C++11 前) 存储类型说明符。(C++11 及以后) 自动类型推断,让编译器根据初始化表达式推断变量的类型。
* `extern`: 存储类型说明符,表示变量或函数的定义在其他文件中,此处仅作声明。
* `typeid`: 运算符,返回一个 `std::type_info` 对象,表示表达式的类型信息。
* ` nullptr`: (C++11) 空指针常量,是一个类型安全的空指针,优于 `NULL` (后者本质上是 `0`)。
* `co_await`, `co_return`, `co_yield`: (C++20) 用于协程(Coroutines)编程。
* `concept`: (C++20) 用于约束模板参数,定义模板的接口要求。
* `requires`: (C++20)
* 在 `concept` 定义中指定约束。
* 作为 `requires` 表达式,用于在模板中进行编译时条件检查。
* `import`, `module`: (C++20) 用于模块(Modules),是一种新的代码组织和依赖管理方式,旨在替代头文件。
* `transaction_safe`, `transaction_safe_dynamic`: (C++20 技术规范) 与事务性内存相关(目前支持有限)。
**示例**:
```cpp
namespace MyApp {
void func() { /* ... */ }
}
using namespace MyApp;
auto name = "Alice"; // C++11, 'name' 被推断为 const char* 类型
int* ptr = nullptr; // C++11, 空指针
template <typename T>
concept Integral = std::is_integral_v<T>;
template <Integral T> // 使用 concept 约束 T 必须是整数类型
T add(T a, T b) {
return a + b;
}
```
### 2.2 C++ 标准中按字母顺序的完整关键字列表
以下是截至 C++23 标准的所有关键字。请注意,一些关键字是在特定版本中引入的。
| 关键字 | 说明 |
| :--- | :--- |
| `alignas` | (C++11) 指定变量或类型的对齐要求。 |
| `alignof` | (C++11) 获取类型的对齐要求。 |
| `and` | 逻辑与运算符 (`&&`) 的替代拼写。 |
| `and_eq` | 按位与赋值运算符 (`&=`) 的替代拼写。 |
| `asm` | 嵌入汇编代码。 |
| `auto` | 自动类型推断 (C++11) / 自动存储期 (C++03)。 |
| `bitand` | 按位与运算符 (`&`) 的替代拼写。 |
| `bitor` | 按位或运算符 (`\|`) 的替代拼写。 |
| `bool` | 布尔类型。 |
| `break` | 跳出循环或 `switch`。 |
| `case` | `switch` 语句的分支。 |
| `catch` | 捕获异常。 |
| `char` | 字符类型。 |
| `char8_t` | (C++20) UTF-8 字符类型。 |
| `char16_t` | (C++11) UTF-16 字符类型。 |
| `char32_t` | (C++11) UTF-32 字符类型。 |
| `class` | 定义类 / 在模板中作为类型参数。 |
| `compl` | 按位取反运算符 (`~`) 的替代拼写。 |
| `concept` | (C++20) 定义概念(约束模板参数)。 |
| `const` | 常量限定符。 |
| `consteval` | (C++20) 强制函数在编译时求值。 |
| `constexpr` | (C++11) 常量表达式或函数。 |
| `const_cast` | 移除 `const` 或 `volatile` 限定符的类型转换。 |
| `continue` | 跳过循环体剩余部分。 |
| `co_await` | (C++20) 协程中等待一个 awaitable 对象。 |
| `co_return` | (C++20) 协程中返回值。 |
| `co_yield` | (C++20) 协程中产生一个值。 |
| `decltype` | (C++11) 推断表达式的类型。 |
| `default` | `switch` 语句的默认分支 / (C++11) 显式默认函数(如构造函数)。 |
| `delete` | 释放动态内存 / (C++11) 显式删除函数。 |
| `do` | `do-while` 循环。 |
| `dynamic_cast` | 动态类型转换。 |
| `else` | `if` 语句的分支。 |
| `else if` | (C++17) `if-else if` 结构的关键字。 |
| `enum` | 定义枚举类型。 |
| `explicit` | 防止隐式类型转换(用于构造函数和转换函数)。 |
| `export` | (C++11 前) 导出模板 (现已移除)。 |
| `extern` | 声明外部链接。 |
| `false` | 布尔值假。 |
| `float` | 单精度浮点类型。 |
| `for` | `for` 循环。 |
| `friend` | 声明友元。 |
| `goto` | 无条件跳转。 |
| `if` | 条件语句。 |
| `inline` | 内联函数。 |
| `int` | 整型。 |
| `long` | 长整型。 |
| `mutable` | 允许 `const` 成员函数修改该成员。 |
| `namespace` | 定义命名空间。 |
| `new` | 动态分配内存。 |
| `noexcept` | (C++11) 指定函数不抛出异常。 |
| `not` | 逻辑非运算符 (`!`) 的替代拼写。 |
| `not_eq` | 不等于运算符 (`!=`) 的替代拼写。 |
| `nullptr` | (C++11) 空指针常量。 |
| `operator` | 重载运算符。 |
| `or` | 逻辑或运算符 (`\|\|`) 的替代拼写。 |
| `or_eq` | 按位或赋值运算符 (`\|=`) 的替代拼写。 |
| `private` | 类成员的私有访问控制。 |
| `protected` | 类成员的保护访问控制。 |
| `public` | 类成员的公有访问控制。 |
| `register` | 寄存器存储建议。 |
| `reinterpret_cast` | 重新解释类型转换。 |
| `requires` | (C++20) 在 `concept` 或 `requires` 表达式中指定约束。 |
| `return` | 从函数返回。 |
| `short` | 短整型。 |
| `signed` | 有符号类型修饰符。 |
| `sizeof` | 获取类型或变量的大小。 |
| `static` | 静态存储期 / 类静态成员。 |
| `static_assert` | (C++11) 编译时断言。 |
| `static_cast` | 静态类型转换。 |
| `struct` | 定义结构体。 |
| `switch` | 多分支选择语句。 |
| `template` | 定义模板。 |
| `this` | 指向当前对象的指针。 |
| `thread_local` | (C++11) 线程本地存储。 |
| `throw` | 抛出异常。 |
| `true` | 布尔值真。 |
| `try` | 异常处理的尝试块。 |
| `typedef` | 类型别名。 |
| `typeid` | 获取类型信息。 |
| `typename` | 模板类型参数 / 表示一个类型。 |
| `union` | 定义联合体。 |
| `unsigned` | 无符号类型修饰符。 |
| `using` | 引入命名空间成员 / 类型别名 / 模板别名。 |
| `virtual` | 虚函数。 |
| `void` | 无类型。 |
| `volatile` | volatile 限定符。 |
| `wchar_t` | 宽字符类型。 |
| `while` | `while` 循环。 |
| `xor` | 按位异或运算符 (`^`) 的替代拼写。 |
| `xor_eq` | 按位异或赋值运算符 (`^=`) 的替代拼写。 |
## 第三部分:C++ 操作符关键字 (Operator Keywords)
这些是一些特殊的符号,它们在语法上是关键字,但实际上是某些运算符的替代拼写。它们主要是为了提供更多的可读性,尤其是在不支持某些特殊字符的键盘或环境中。
* `and` (`&&`)
* `and_eq` (`&=`)
* `bitand` (`&`)
* `bitor` (`|`)
* `compl` (`~`)
* `not` (`!`)
* `not_eq` (`!=`)
* `or` (`||`)
* `or_eq` (`|=`)
* `xor` (`^`)
* `xor_eq` (`^=`)
**示例**:
```cpp
if (a and b) { // 等同于 if (a && b)
// ...
}
x or_eq y; // 等同于 x |= y;
```
## 第四部分:C++ 预处理器指令 (Preprocessor Directives)
预处理器指令是在编译之前由预处理器处理的命令。它们以井号 `#` 开头,并且不在行尾使用分号。虽然它们不是 C++ 语言本身的关键字,但它们是 C++ 程序不可或缺的一部分,并且具有特殊的语法地位。
* `#define`: 宏定义。
* `#elif`: `#if` 指令的 "else if" 分支。
* `#else`: `#if` 或 `#elif` 指令的 else 分支。
* `#endif`: 结束一个 `#if`, `#ifdef`, 或 `#ifndef` 块。
* `#error`: 编译时产生一个错误消息。
* `#if`: 根据条件编译代码。
* `#ifdef`: 如果宏已定义,则编译代码。
* `#ifndef`: 如果宏未定义,则编译代码。
* `#include`: 包含一个头文件。
* `#line`: 改变当前的行号和文件名(主要用于生成的代码)。
* `#pragma`: 向编译器发出特定的指令(如 `#pragma once`)。
* `#undef`: 取消一个宏定义。
**示例**:
```cpp
#include <iostream>
#define DEBUG_MODE
#ifdef DEBUG_MODE
#define LOG(x) std::cout << "[DEBUG] " << x << std::endl
#else
#define LOG(x)
#endif
int main() {
LOG("Program started."); // 在 DEBUG_MODE 下会输出
return 0;
}
```
## 总结
标识符和关键字是 C++ 语言的基石。
* **标识符**是程序员赋予程序元素的名称,其命名质量直接影响代码的可读性和可维护性。遵循清晰、一致的命名规范是专业编程的基本要求。
* **关键字**是 C++ 语言预定义的、具有特殊意义的词汇,它们构成了语言的语法结构。熟悉所有关键字及其用法,特别是 C++11 及以后版本引入的现代特性(如 `auto`, `constexpr`, `nullptr`, `template`, `concept` 等),对于编写高效、健壮和现代的 C++ 代码至关重要。
* **操作符关键字**是标准运算符的同义词,主要用于提高代码可读性或兼容性。
* **预处理器指令**虽然不属于核心语言,但在控制编译流程、管理代码版本和配置方面扮演着重要角色。
希望这份详尽的指南能帮助你全面掌握 C++ 的标识符和关键字,为你的编程学习和实践打下坚实的基础。
更多推荐


所有评论(0)