C++ 快速入门
C++ 快速入门
环境配置
Windows:安装 Visual Studio 2022
推荐 Windows 用户使用 Visual Studio 2022,编译器、调试器、编辑器一体,不需要额外配置。
1. 下载安装包
前往 https://visualstudio.microsoft.com,选择 Community 2022(免费版),下载后运行安装程序。
2. 选择工作负载
安装程序会让你选择要安装的组件,勾选 “使用 C++ 的桌面开发”,右侧详细列表中确认以下三项已选中:
- MSVC v143(编译器本体)
- Windows SDK(系统头文件和库)
- C++ CMake 工具(可选,后续可能用到)
其余默认即可,点击安装,等待完成(约 5–10 GB)。
3. 创建第一个项目
安装完成后打开 Visual Studio:
- 点击 “创建新项目”
- 搜索并选择 “控制台应用”(语言选 C++)
- 填写项目名称和保存路径,点击 “创建”
VS 会自动生成一个包含 main 函数的 .cpp 文件。
Linux:安装编译器与工具链
Ubuntu / Debian
1 | |
build-essential 包含 gcc、g++ 和 make,gdb 是调试器,cmake 是构建工具。
安装完成后验证:
1 | |
编辑器推荐:安装 VS Code,再安装插件 C/C++(Microsoft 官方),可以获得语法高亮、跳转定义、调试支持。
第一个程序
在 VS 自动生成的文件里,或者新建一个 .cpp 文件,写入:
1 | |
Windows(Visual Studio)运行方式:
- 按
Ctrl + F5直接运行(不调试) - 按
F5以调试模式运行 - 底部输出窗口会显示
Hello C++
Linux 编译运行方式:
1 | |
调试基本操作
调试能力越早建立越好,读复杂代码时依赖它的频率远超预期。以 Visual Studio 为例:
| 操作 | 快捷键 | 说明 |
|---|---|---|
| 打 / 取消断点 | F9 | 点击行号左侧也可以 |
| 启动调试 | F5 | 程序运行到断点处暂停 |
| 逐行执行 | F10 | 不进入函数内部 |
| 进入函数 | F11 | 跳入当前行调用的函数 |
| 跳出函数 | Shift+F11 | 执行完当前函数剩余部分,返回调用处 |
| 继续运行 | F5 | 运行到下一个断点 |
程序暂停在断点时,鼠标悬停在变量上可以直接看到它的当前值;左下角的 “局部变量” 窗口会列出当前作用域内所有变量。
C++ 最小生存集
基础语法
变量与类型
C++ 是强类型语言,变量必须声明类型:
1 | |
auto 可以让编译器自动推断类型,在类型名很长时常用:
1 | |
函数
1 | |
条件与循环
1 | |
enum class
比起裸 enum,enum class 有独立的作用域,不会污染外部命名空间,项目里更常见:
1 | |
指针与引用
1 | |
在实际项目里这两种写法有明确的语义约定:指针传参暗示调用方可能传入空值,函数内需要判空;引用传参暗示对象一定有效,直接使用。读函数签名时先看这一点,能快速判断函数的前提条件。
const
1 | |
最常见的形式:
1 | |
函数签名末尾的 const 表示该函数不修改当前对象的任何成员,是一个只读操作。
本阶段不需要掌握
- 宏技巧
- 运算符重载
- 多继承的复杂规则
面向对象与多态
类、构造与析构
1 | |
需要理解两个概念:
- 构造/析构顺序:派生类构造时先调用基类构造函数,析构顺序相反
- 栈对象 vs 堆对象:栈对象离开作用域自动析构,堆对象(
new出来的)需要显式delete,或者交给智能指针管理
继承与虚函数
1 | |
虚析构函数不能省。 用基类指针 delete 派生类对象时,如果基类析构函数不是虚函数,派生类的析构函数不会执行,资源泄漏。
override 不是可选的。 它让编译器验证父类里确实存在这个虚函数——函数名拼错、或者父类签名变了,编译期就会报错,而不是悄悄变成一个新函数。
构造/析构里不要调用虚函数。 基类构造函数执行时,派生类尚未构造完成,此时调用虚函数走的是基类版本,不是预期的派生类版本。
多态与调试
遇到 Base* obj 调用 obj->Execute(),不确定实际执行的是哪个子类实现时,在调用处打断点,F11 单步进入,调试器会跳到真实的派生类方法。
智能指针与 RAII
unique_ptr
1 | |
对象的唯一拥有者,离开作用域自动销毁,不需要手动 delete。
unique_ptr 不能复制,只能转移所有权:
1 | |
函数参数是 unique_ptr 时,意味着调用后所有权转移给了被调函数。
shared_ptr 与 weak_ptr
1 | |
最后一个持有者销毁时,对象才真正释放。
循环引用是共享所有权的常见陷阱——A 持有 B,B 也持有 A,引用计数永远不归零。解决方式是其中一方改用 weak_ptr:
1 | |
weak_ptr 不增加引用计数,只是一个”不参与所有权”的观察者。
RAII
C++ 管理资源的核心惯用法:
构造函数 = 获取资源
析构函数 = 释放资源
智能指针、lock_guard、各种 handle 封装类,本质上都是 RAII。对象生命周期结束,资源跟着释放,适用于所有需要配对操作的场景:内存、锁、文件句柄、回调注册等。
模板、Lambda 与回调
模板
项目里最常见的模板形式:
1 | |
理解为”该函数适用于任意类型 T”即可。
编译期约束:
1 | |
static_assert 在编译期检查类型条件,T 不满足要求时直接报错。这类断言是函数契约的一部分,能帮助理解调用前提。
可变参数模板偶尔会遇到:
1 | |
知道它接受任意数量、任意类型的参数就够了,不需要深入。
Lambda
1 | |
方括号是捕获列表:
[this]:捕获当前对象指针,可以访问成员变量和成员函数[&]:按引用捕获所有外部变量[=]:按值捕获(复制)所有外部变量
捕获 this 的生命周期问题:如果 lambda 的存活时间超过 this 对象,对象析构后 lambda 被触发,程序崩溃。注册回调时需要确保回调生命周期不超过 this,或者在对象析构前主动注销。
std::function
1 | |
可以包装任何符合该签名的可调用对象:普通函数、lambda、绑定的成员函数。是回调系统常用的存储类型,有一定运行时开销,用于热路径时需要注意。
并发基础
mutex 与 lock_guard
1 | |
lock_guard 是 RAII 在锁上的应用,不需要手动解锁,异常安全,优先使用它而不是手写 lock / unlock。
某些场景下会看到 recursive_mutex,用于同一线程可能递归进入同一临界区的情况——普通 mutex 在这种情况下会死锁。
atomic
1 | |
用于简单的计数器场景,比 mutex 轻量。
如何读一个陌生的类
进入实际项目后,对每个陌生的类问自己 5 个问题:
- 谁创建它? 找构造函数在哪里被调用
- 谁持有它? 看谁持有它的指针或智能指针
- 生命周期多长? 析构函数何时执行
- 是否使用多态? 虚函数的真实实现在哪个子类
- 是否涉及线程安全? 有没有锁,锁保护的范围是什么
能力检验
- 看到
unique_ptr作为函数参数,清楚所有权在调用后如何转移 - 看到带捕获列表的 lambda,知道它能访问哪些外部变量,以及潜在的生命周期风险
- 看到虚函数调用,能用调试器定位到真正执行的派生类实现
- 看到含模板与回调的头文件,能逐段读下去
CMake:构建系统入门
它解决什么问题
写一个文件用 g++ hello.cpp -o hello 编译完全够用。但真实项目通常有几十乃至几百个 .cpp 文件,还会依赖各种第三方库,不同成员可能分别用 Windows、Linux、macOS 开发。这时候靠手写编译命令已经不现实——CMake 就是用来描述”这个项目该怎么编译”的工具。
CMake 本身不是编译器,它读取你写的构建描述文件(CMakeLists.txt),然后生成对应平台的构建文件:Windows 上生成 Visual Studio 项目,Linux 上生成 Makefile 或 Ninja 构建文件,再交给编译器去实际编译。
1 | |
读开源项目或接手别人的代码时,项目根目录里有 CMakeLists.txt 是常态,看懂它才能知道这个项目是如何组织的。
CMakeLists.txt 基本结构
一个最简单的单文件项目:
1 | |
多个源文件:
1 | |
引入第三方库(以 CMake 内置的 find_package 为例):
1 | |
如何构建项目
CMake 的标准流程分两步:配置和构建,必须在单独的构建目录里操作(不要在源码目录里直接运行 CMake,会污染源码)。
Linux / macOS:
1 | |
Windows(Visual Studio 直接打开):
VS 2022 支持直接打开包含 CMakeLists.txt 的文件夹(文件 → 打开 → 文件夹),会自动识别并配置,不需要手动生成项目文件。这是 Windows 上处理 CMake 项目最省事的方式。
Windows(命令行):
1 | |
Debug 与 Release
1 | |
开发阶段始终用 Debug 构建。如果发现断点无法命中、变量值显示异常,通常是误用了 Release 构建。
实战:从零搭一个多文件项目
下面用一个具体的例子把上面的内容串起来。目标是建一个包含两个 .cpp 文件的项目,编译后能运行。
项目结构:
1 | |
greeter.h:
1 | |
greeter.cpp:
1 | |
main.cpp:
1 | |
CMakeLists.txt:
1 | |
构建并运行(Linux):
1 | |
构建并运行(Windows,Visual Studio 打开文件夹):
文件 → 打开 → 文件夹,选择myproject/- VS 自动检测到
CMakeLists.txt并完成配置 - 顶部工具栏选择
MyProject.exe,按F5运行
遇到陌生 CMake 项目时的处理流程
- 看根目录的
CMakeLists.txt,找project()确认项目名,找add_executable或add_library确认会生成什么 - 看有没有
README,通常会写构建步骤 - 按标准流程
cmake -S . -B build→cmake --build build尝试构建 - 构建报错时,优先看第一条错误,后续错误通常是连锁反应