Skip to content

C++ 快速指南

C++ 是一种功能强大的、静态类型、编译型、多范式编程语言。它支持面向过程、面向对象、泛型和函数式编程风格。它以其高性能而闻名,广泛应用于系统编程、游戏开发、高频交易、嵌入式系统和大型应用程序。

C++ 被视为一种中级语言,它既提供低级内存操作能力(如 C 语言),也提供高级抽象(如类和模板)。C++ 通过标准不断发展(C++11, C++14, C++17, C++20, C++23…),现代 C++ 强调安全性、表达性和性能。

你需要一个 C++ 编译器来将你的源代码(通常在 .cpp 文件中)翻译成可执行程序。流行的现代编译器包括:

  • GCC (GNU Compiler Collection): 免费、开源,广泛用于 Linux、macOS(通过 Xcode Command Line Tools 或包管理器)和 Windows(通过 MinGW 或 Cygwin)。
  • Clang: 免费、开源编译器(LLVM 项目的一部分),以快速编译和出色的诊断闻名。可在主要平台上使用。
  • MSVC (Microsoft Visual C++): Windows 上 Visual Studio 的一部分。提供免费的 Community 版本。

确保你的编译器支持最新的 C++ 标准(推荐 C++17 或更高版本以使用现代特性)。

一个最小的 C++ 程序:

// 包含标准库功能所需的头文件
#include <iostream> // 用于输入/输出流 (例如 std::cout)
// main() 是程序执行的入口点。
// 它应该返回一个整数状态码 (通常 0 表示成功)。
int main() {
// std::cout 是标准输出流 (通常是控制台)。
// << 是流插入运算符。
// std::endl 插入换行符并刷新输出缓冲区。
std::cout << "Hello, Modern C++!" << std::endl;
return 0; // 表示成功执行
}

注释会被编译器忽略,用于解释代码。

// 这是单行注释。它会延伸到行尾。
/*
这是多行注释。
它可以跨越多行。
*/

C++ 有几种内置(原始)数据类型:

类型关键字典型用途
布尔型bool真/假值 (true, false)
字符型char单个字符 (例如 ‘a’, ’$’)。也用于小整数。
整型int整数 (例如 10, -5, 0)
浮点型float单精度小数 (例如 3.14f)
双精度浮点型double双精度小数 (例如 3.14159)
无值型void表示无类型 (用于函数返回类型、指针)
宽字符型wchar_t用于更大字符集 (实现定义) 的字符

修饰符 (signed, unsigned, short, long, long long) 可以改变这些类型的范围和大小(参见 cpp_modifier_types.json)。

变量定义指定其类型和名称,并分配内存。初始化赋予其初始值。

#include <string>
#include <vector>
int main() {
int score = 90; // C 风格初始化
double temperature(25.5); // 构造函数风格初始化
bool isActive{true}; // 统一初始化 (在现代 C++ 中更推荐)
std::string playerName = "Alex"; // 使用字符串字面量初始化
std::vector<int> numbers{1, 2, 3}; // 容器的统一初始化
// 使用 'auto' 进行类型推导 (C++11)
auto count = 10; // count 被推导为 int
auto message = "Processing..."; // message 被推导为 const char*
auto pi = 3.14; // pi 被推导为 double
return 0;
}

始终初始化你的变量,以避免使用不确定的值。

作用域定义了变量可以在何处被访问:

  • 局部作用域 (Local Scope): 在函数或块 ({}) 内声明的变量只能在该函数/块内访问。
  • 全局作用域 (Global Scope): 在任何函数外部声明的变量具有全局作用域,可以在文件中的任何地方(在声明之后)访问。谨慎使用全局变量。
  • 类作用域 (Class Scope): 类的成员可以在类方法内访问(以及可能在外部,取决于访问说明符)。
  • 命名空间作用域 (Namespace Scope): 在命名空间内声明的变量。

字面量是代码中固定的值(例如 10, 3.14f, 'a', "Hello")。常量是初始化后其值不能更改的变量。

const double PI = 3.14159; // 'const' 关键字用于运行时常量
constexpr int MAX_USERS = 100; // 'constexpr' 用于编译时常量
// PI = 3.14; // 错误:无法赋值给 const 变量
// MAX_USERS = 99; // 错误:无法赋值给 constexpr 变量

使用 const 和 constexpr 可以提高代码安全性并启用优化。

存储类说明符决定变量的生命周期和链接属性:

  • auto (作为存储类已过时,关键字在 C++11 中重新用于类型推导)
  • register (对编译器的提示,很大程度上被现代优化器忽略)
  • static: 在函数/块内部,将其生命周期延长到整个程序持续时间。在全局/命名空间作用域,限制链接到当前翻译单元。
  • extern: 声明在别处(通常在另一个文件)定义的变量,启用链接。
  • thread_local (C++11): 指定变量具有线程局部存储期。
  • mutable: 允许声明为 mutable 的类成员即使在 const 成员函数内或通过 const 对象也能被修改。

C++ 提供了丰富的运算符集合:

  • 算术运算符 (Arithmetic): +, -, *, /, % (取模), ++ (自增), -- (自减)
  • 关系运算符 (Relational): == (等于), != (不等于), >, <, >=, <=
  • 逻辑运算符 (Logical): && (与), || (或), ! (非)
  • 位运算符 (Bitwise): & (按位与), | (按位或), ^ (按位异或), ~ (按位非), << (左移), >> (右移)
  • 赋值运算符 (Assignment): =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
  • 成员访问运算符 (Member Access): . (对象成员), -> (指针成员)
  • 其他运算符 (Other): sizeof, & (取地址), * (解引用), ?: (三元条件运算符), , (逗号), () (函数调用), [] (数组下标), typeid, 转换运算符 (static_cast, dynamic_cast, const_cast, reinterpret_cast), new, delete, :: (作用域解析)

循环重复执行代码块:

循环类型描述
while 循环当条件为真时重复执行(在每次迭代之前检查)。
for 循环执行指定次数(初始化、条件、更新)。
do...while 循环当条件为真时重复执行(在每次迭代之后检查;循环体总是至少执行一次)。
基于范围的 for 循环 (Range-based for, C++11)迭代范围内的所有元素(例如,容器、数组)。简单的迭代场景首选。
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {10, 20, 30};
// 基于范围的 for 循环 (现代 C++)
for (int num : nums) {
std::cout << num << " "; // 输出: 10 20 30
}
std::cout << std::endl;
// 传统 for 循环
for (size_t i = 0; i < nums.size(); ++i) {
std::cout << nums[i] << " "; // 输出: 10 20 30
}
std::cout << std::endl;
return 0;
}

根据条件控制执行的语句:

语句描述
if 语句如果条件为真则执行代码。
if...else 语句如果条件为真则执行一个代码块,否则执行另一个。
if...else if...else链式处理多个条件。
switch 语句将变量与一系列常量值 (case) 进行比较测试。
三元运算符 (?:)简单 if-else 表达式的缩写形式。

函数将代码组织在一起以执行特定任务。

// 函数定义
return_type function_name(parameter_list) {
// 函数体
return value; // 可选,取决于 return_type
}
  • return_type: 函数返回值的类型(如果无返回值,则为 void)。
  • function_name: 函数的标识符。
  • parameter_list: 用逗号分隔的输入参数列表(类型和名称)。
  • function body: 函数被调用时执行的代码。

函数提高了代码复用性和模块化。

使用原始类型 (int, float, double) 表示数字。包含 <cmath> 以使用数学函数。

#include <cmath> // 用于数学函数
#include <iostream>
int main() {
double angle_degrees = 45.0;
double angle_radians = angle_degrees * M_PI / 180.0; // M_PI 通常需要 _USE_MATH_DEFINES 或类似定义
std::cout << "Square root of 16: " << std::sqrt(16.0) << std::endl; // 输出: 4
std::cout << "2 raised to power 10: " << std::pow(2.0, 10.0) << std::endl; // 输出: 1024
std::cout << "Cosine of 45 degrees: " << std::cos(angle_radians) << std::endl; // 输出: ~0.7071
return 0;
}

对于高质量的随机数,请使用 <random> 头文件(参见 cpp_numbers.json)。

数组存储固定大小的元素序列。在现代 C++ 中,优先使用 std::vector 或 std::array,而非原始 C 风格数组。

#include <vector> // 用于 std::vector (动态大小)
#include <array> // 用于 std::array (固定大小, 栈分配)
#include <iostream>
#include <numeric> // 用于 std::iota
int main() {
// C 风格数组 (谨慎使用)
int c_array[5];
c_array[0] = 10;
// std::array (固定大小, 使用 .at() 进行边界检查)
std::array<int, 5> modern_array;
std::iota(modern_array.begin(), modern_array.end(), 100); // 填充 100, 101, ...
std::cout << "std::array element: " << modern_array.at(1) << std::endl; // 输出: 101
// std::vector (动态大小, 自行管理内存)
std::vector<int> dynamic_vector;
dynamic_vector.push_back(10);
dynamic_vector.push_back(20);
dynamic_vector.push_back(30);
std::cout << "Vector size: " << dynamic_vector.size() << std::endl; // 输出: 3
std::cout << "Vector element: " << dynamic_vector[1] << std::endl; // 输出: 20
// 使用基于范围的 for 循环迭代
for (int val : dynamic_vector) {
std::cout << val << " "; // 输出: 10 20 30
}
std::cout << std::endl;
return 0;
}

使用 <string> 头文件中的 std::string 类进行文本操作。对于一般的字符串处理,避免使用 C 风格的字符数组 (char[])。

#include <string>
#include <iostream>
int main() {
std::string greeting = "Hello";
std::string name = "World";
std::string message;
// 字符串连接
message = greeting + ", " + name + "!";
std::cout << message << std::endl; // 输出: Hello, World!
// 长度/大小
std::cout << "Message length: " << message.length() << std::endl;
// 子串
std::cout << "Substring: " << message.substr(0, 5) << std::endl; // 输出: Hello
return 0;
}

类是对象的蓝图,封装了数据(成员)和行为(方法)。

#include <iostream>
#include <string>
class Box {
private: // 数据成员通常是私有的 (Encapsulation - 封装)
double length = 1.0;
double breadth = 1.0;
double height = 1.0;
public: // 方法 (和构造函数) 通常是公有的
// 构造函数 (初始化对象)
Box(double l, double b, double h) : length(l), breadth(b), height(h) {
std::cout << "Box created with dimensions: " << l << ", " << b << ", " << h << std::endl;
}
// 成员函数 (方法)
double getVolume() const { // const 表示该方法不修改对象
return length * breadth * height;
}
// 析构函数 (对象销毁时进行清理)
~Box() {
std::cout << "Box destroyed." << std::endl;
}
};
int main() {
// 创建 Box 类的一个对象 (实例)
Box myBox(5.0, 6.0, 7.0);
// 使用点 (.) 运算符访问公有成员
std::cout << "Volume of myBox: " << myBox.getVolume() << std::endl;
return 0; // myBox 在此处超出作用域,调用析构函数 ~Box()
}

关键的面向对象编程 (OOP) 概念,如封装 (Encapsulation)、抽象 (Abstraction)、继承 (Inheritance) 和多态 (Polymorphism),是 C++ 的核心(参见 cpp_object_oriented.json)。

允许基于现有类(基类)创建新类(派生类),提高代码复用性并体现“is-a”关系。

class Shape { // 基类
public:
virtual double getArea() const = 0; // 纯虚函数 (使 Shape 成为抽象类)
virtual ~Shape() = default; // 虚析构函数!
};
class Rectangle : public Shape { // 派生类
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double getArea() const override { // 实现基类虚函数,使用 'override'
return width * height;
}
};

有关访问说明符、虚函数、override、final 和多重继承的详细信息,请参阅 cpp_inheritance.json。

允许多个不同派生类的对象通过共同的基类接口进行处理,通常使用指针或引用。

#include <iostream>
#include <memory> // 用于 std::unique_ptr
#include <vector>
// 使用来自继承示例的 Shape 和 Rectangle...
void printArea(const Shape& shape) { // 接收基类引用
std::cout << "Area: " << shape.getArea() << std::endl;
}
int main() {
Rectangle rect(10, 5);
// Circle circ(7); // 假设有一个从 Shape 派生的 Circle 类
printArea(rect); // 调用 Rectangle::getArea()
// printArea(circ); // 会调用 Circle::getArea()
// 使用基类指针 (首选智能指针)
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Rectangle>(4, 3));
// shapes.push_back(std::make_unique<Circle>(2));
for (const auto& shapePtr : shapes) {
printArea(*shapePtr); // 通过虚派发调用适当的 getArea()
}
return 0;
}

需要在基类中包含 virtual 函数。对于打算用于多态的基类,请始终包含 virtual 析构函数。

允许具有相同名称但不同参数的多个函数或运算符(编译时多态)。

void display(int i) { std::cout << "Int: " << i << std::endl; }
void display(double d) { std::cout << "Double: " << d << std::endl; }
void display(const std::string& s) { std::cout << "String: " << s << std::endl; }
display(10); // 调用 int 版本
display(3.14); // 调用 double 版本
display("Test"); // 调用 string 版本

使用 <fstream> 进行文件 I/O(std::ifstream 用于输入,std::ofstream 用于输出)。

#include <fstream> // 用于文件流
#include <iostream> // 用于控制台 I/O
#include <string> // 用于 std::string
#include <vector>
int main() {
std::string filename = "mydata.txt";
// 写入文件 (使用 RAII 和 ofstream)
{
std::ofstream outfile(filename); // 在构造函数中打开文件
if (!outfile) { // 始终检查文件是否成功打开
std::cerr << "Error opening " << filename << " for writing." << std::endl;
return 1;
}
outfile << "Line 1: Hello from C++\n";
outfile << "Line 2: Files are useful.\n";
} // outfile 超出作用域,文件自动关闭
// 从文件读取
{
std::ifstream infile(filename);
if (!infile) {
std::cerr << "Error opening " << filename << " for reading." << std::endl;
return 1;
}
std::string line;
std::cout << "\nReading from file:" << std::endl;
while (std::getline(infile, line)) { // 逐行读取
std::cout << line << std::endl;
}
} // infile 超出作用域,文件自动关闭
return 0;
}

始终检查文件流是否成功打开。RAII(直接使用流对象)确保即使发生错误也能关闭文件。

本快速指南提供了一个起点。C++ 是一门博大精深的语言;请查阅 cppreference.com 等资源和专门的教程以获取更多信息。