C++ 文档
简洁、以示例为主的 C++ 参考文档。先读概念,再看代码,然后在 Coddy 学习旅程中动手练习。
开始课程入门
- C++ 是什么C++ 到底是什么,它为什么能直接编译成本地机器码,以及人们用它来构建哪些高性能软件。
- Hello World逐行讲解 C++ 的 Hello World 程序:#include <iostream>、int main()、std::cout 和 <<、std::endl 与 '\n' 的区别、return 0,以及如何编译它、如何修复初学者最先遇到的错误。
- 安装 C++如何安装 C++ 编译器(GCC、Clang 或 MSVC),为你的操作系统选择合适的工具链,并在命令行中确认它能正常工作。
- 编译 C++C++ 如何把 .cpp 源代码变成本机可执行文件:用 g++(或 clang++/MSVC)编译,运行生成的程序,以及出错时如何读懂编译器的错误信息。
- C++ 语法C++ 程序的核心语法规则:语句和分号、花括号代码块、main 函数以及输出的工作方式,从第一个程序开始讲起。
- 注释如何在 C++ 中写注释:单行的 // 和多行的 /* */ 块注释,以及如何注释掉代码、为什么块注释不能嵌套、什么样的注释值得保留。
变量与类型
- 变量C++ 中的变量是怎么工作的:用类型声明变量、赋值与初始化的区别、花括号初始化、命名规则,以及决定变量在哪里诞生和销毁的作用域。
- 数据类型实用的 C++ 基本数据类型指南:整数、浮点数、char 和 bool,以及类型大小、有符号与无符号、字面量和后缀、溢出,还有怎样选择合适的类型。
- auto 关键字`auto` 关键字如何让编译器替你推导变量的类型:它会去掉什么、在哪里最好用,以及让新手栽跟头的陷阱。
- 常量与 const在 C++ 中如何用 const 声明只读的值,const 和 constexpr 有什么区别,const 指针与指向 const 的指针,以及 const 成员函数。
- 运算符学习 C++ 运算符:算术、比较、逻辑、赋值和位运算符,以及整数除法、优先级和短路求值方面的陷阱。
- 类型转换C++ 中的类型转换是怎么工作的:隐式转换、整数除法陷阱,以及四种具名转换(static_cast、const_cast、reinterpret_cast、dynamic_cast),还有那些会悄悄丢失数据的坑。
流程控制
- if-else如何在 C++ 中用 if、else if 和 else 做判断:条件、多分支链、嵌套、三元运算符、带初始化语句的 if,以及容易让人踩坑的地方。
- switch讲解 C++ 的 switch 语句:case 标签、break 与贯穿、default 分支、合并多个 case、对枚举使用 switch,以及在 case 中声明变量的陷阱。
- for 循环如何用 C++ 的 for 循环重复执行代码:三段式循环头、正向和反向计数、遍历数组、嵌套循环、break 和 continue,以及几乎人人都会踩的差一错误和无符号数陷阱。
- while 循环详解 C++ while 循环:先判断条件的 while、至少执行一次的 do-while、循环直到遇到哨兵值、break 和 continue,以及如何避免死循环。
- 范围 for 循环讲解 C++ 的范围 for 循环:简洁地遍历数组、vector、字符串和 map,为什么要用 auto& 和 const auto&,以及要避开的拷贝陷阱和迭代器失效陷阱。
函数
- 函数如何在 C++ 中编写函数:返回类型、函数名、参数的基本结构,声明与定义的区别,返回值,void 函数,以及漏写 return、忘记函数原型等常见的坑。
- 函数参数实参是怎样进入 C++ 函数的:值传递与引用传递、用 const 引用实现低成本的只读访问、默认实参、指针参数,以及那些悄悄拖慢程序的复制开销陷阱。
- 引用讲解 C++ 引用:参数中的 & 如何创建别名,为什么引用传递能避免拷贝,并让函数修改调用者的变量,什么时候该用 const&,以及引用与返回值的取舍。
- 函数重载C++ 函数重载让多个函数共用一个名字,只要它们的参数列表不同。学习重载决议如何选出匹配的版本、为什么仅返回类型不同不算重载,以及要避开的二义性和默认实参陷阱。
- Lambda用 C++ lambda 随手写出简短的内联函数:语法、捕获的工作方式、何时使用 `mutable`,以及人人都会踩到的悬空捕获陷阱。
指针与内存
- 指针从零讲解 C++ 指针:如何声明指针,取地址运算符 & 和解引用运算符 *,nullptr,指向数组的指针,以及会让程序崩溃的悬空指针和未初始化指针陷阱。
- 引用与指针实用地对比 C++ 中的引用和指针:它们的共同点,它们的不同之处(重新绑定、空值、指针运算),以及日常代码中该选哪一个的清晰规则。
- 动态内存如何在运行时用 `new` 分配内存、用 `delete` 释放内存,以及如何避开手动管理堆内存时常见的内存泄漏、悬空指针和重复释放。
- 智能指针智能指针拥有堆内存,并会自动释放它。学习 `unique_ptr`、`shared_ptr`、`make_unique` 和 `make_shared`,以及为什么你几乎再也不需要写 `new`/`delete`。
字符串与输入输出
- 字符串如何在 C++ 中使用 `std::string`:安全地创建、拼接、查找和截取文本,以及为什么正经开发中你几乎永远不想用裸 `char*`。
- 输入与输出C++ 中控制台输入输出的原理:用 cout 打印,用 cin 读取,cin 之后 getline 读到换行符的经典 bug,以及输入失败后如何恢复。
- std::getlinestd::getline 如何把一整行读入 std::string:配合 cin 使用,为什么在 cin >> 之后它会返回空字符串,cin.ignore 和 std::ws 两种修复方法,自定义分隔符,以及逐行读取文件直到文件末尾。
- 字符串流如何使用 std::stringstream、istringstream 和 ostringstream 解析文本、按空白分割字符串、在字符串和数字之间转换,以及在内存中拼出格式化字符串。
STL 容器
- 数组C++ 原生数组详解:如何声明和初始化、安全地用下标访问、按长度遍历、数组退化为指针的陷阱,以及为什么 std::array 和 vector 通常更好。
- vectorstd::vector 是 C++ 中可变大小的数组,也是你默认应该首选的容器。学习如何创建、访问、扩充和遍历 vector,以及迭代器失效和越界访问这两个陷阱。
- mapC++ std::map 详解:一种按键排序、查找为对数时间的键值容器。插入、查找、遍历,并避开 operator[] 会悄悄插入键的经典陷阱。
- unordered_map学习 C++ 中的 std::unordered_map:它是 map 的哈希表版本,插入和查找的平均复杂度是 O(1)。内容包括基本操作、[] 自动插入的陷阱、count 与 find 的区别,以及什么时候该用它代替有序的 map。
- setstd::set 如何在 C++ 中存储唯一且自动排序的值:插入元素,用 count 和 find 检查元素是否存在,按顺序遍历,以及 set、multiset 和 unordered_set 之间的区别。
- pair 和 tuple`std::pair` 和 `std::tuple` 如何把两个或更多值打包成一个对象:创建方式、访问字段、结构化绑定,以及各自适用的场景。
- 迭代器C++ 迭代器如何作为指向容器元素的泛化指针工作:begin() 和 end()、解引用、前进、const 和反向迭代器,以及迭代器失效、解引用 end() 等会导致未定义行为的陷阱。
STL 算法与模板
类与对象
- 类学习 C++ 的类如何把数据和行为打包成可复用的类型:声明成员变量和方法、创建对象、public/private 的划分,以及未初始化的成员和 this 指针等陷阱。
- 构造函数构造函数是在对象创建时运行的特殊成员函数。学习默认构造函数、带参构造函数、拷贝构造函数和成员初始化列表,以及怎样避免对象只初始化了一半。
- 析构函数析构函数在对象被销毁时自动运行。学习 `~ClassName()` 语法、它在什么时候触发、为什么由它释放资源,以及三/五法则。
- 继承了解 C++ 继承如何让派生类复用并扩展基类:语法、public 与 private 继承、构造函数和析构函数的调用顺序,以及对象切片等常见陷阱。
- 虚函数虚函数让基类指针在运行时调用派生类版本的方法。学习 `virtual`、`override`、抽象类,以及为什么基类的析构函数必须是虚函数。
- 运算符重载C++ 运算符重载让你自己的类型也能使用 +、==、<< 等内置运算符。了解成员函数与非成员函数的选择规则、如何重载比较运算符和流运算符,以及返回类型和赋值运算符方面的陷阱。
- 访问修饰符C++ 中 public、private 和 protected 如何控制谁能访问类的成员:这是封装的基础,还包括 getter、setter 和 friend 这个例外通道。
- 结构体讲解 C++ 结构体:如何把相关的变量打包成一个类型,声明和初始化结构体对象,给结构体加上成员函数和构造函数,以及 struct 和 class 的真正区别。
- 枚举学习 C++ 枚举:如何声明枚举,为什么作用域枚举 enum class 比普通 enum 更安全,自定义底层值,在 switch 中使用枚举值,以及与整数之间的相互转换。