Skip to content

Commit 44fa6da

Browse files
committed
book: write Appendix 2 (modern C++ best practices)
Replace the TODO stubs with concrete, widely-accepted best practices across tools, coding style, performance, safety, maintainability, and portability. Reword the intro to reference the C++ Core Guidelines and frame the content as generally accepted practice rather than secret tips. Refs #1
1 parent 328e8dc commit 44fa6da

2 files changed

Lines changed: 60 additions & 14 deletions

File tree

book/en-us/appendix2.md

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,54 @@ order: 12
66

77
# Appendix 2: Modern C++ Best Practices
88

9-
In this appendix we will briefly talk about the best practices of modern C++. In general, the author's thoughts on C++'s best practices are mainly absorbed from [Effective Modern C++](https://www.amazon.com/dp/1491903996/ref=cm_sw_em_r_mt_dp_U_-ZgjDb81ERBNP) and [C++ Style Guide](https://google.github.io/styleguide/cppguide.html). In this appendix, we will briefly discuss and use the actual examples to illustrate the methods, and introduce some of **the author's personal**, **non-common**, **non-sensible** best practices, and how to ensure the overall quality of the code.
9+
In this appendix we briefly discuss the best practices of modern C++. Many of these ideas are distilled from [Effective Modern C++](https://www.amazon.com/dp/1491903996/) and the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html), as well as the [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) maintained by Bjarne Stroustrup and Herb Sutter. The goal of this appendix is to summarize widely accepted practices that help ensure the overall quality of your code.
1010

1111
## Common Tools
1212

13-
TODO:
13+
Good tooling catches a large class of problems before they ever reach production:
14+
15+
- **Enable warnings, and treat them as errors.** Compile with `-Wall -Wextra` (and consider `-Wpedantic`); `-Werror` keeps warnings from accumulating.
16+
- **Run sanitizers during testing.** AddressSanitizer (`-fsanitize=address`), UndefinedBehaviorSanitizer (`-fsanitize=undefined`) and ThreadSanitizer (`-fsanitize=thread`) catch memory errors, undefined behavior, and data races at run time.
17+
- **Format and lint automatically.** `clang-format` keeps style consistent, and `clang-tidy` flags bug-prone patterns and suggests modernizations.
18+
- **Use a modern build system and package manager**, such as CMake together with vcpkg or Conan, to make builds reproducible.
19+
- **Experiment quickly** with [Compiler Explorer](https://godbolt.org/) to inspect the generated assembly and compare compilers and standards.
1420

1521
## Coding Style
1622

17-
TODO:
23+
A consistent style makes a codebase far easier to read and maintain:
24+
25+
- Pick a style guide and apply it consistently across the whole project; consistency matters more than the specific choices.
26+
- Be `const`-correct: mark variables, member functions, and parameters `const` whenever they do not need to mutate state.
27+
- Use `auto` to avoid redundant type spelling, but not at the cost of readability — keep the reader able to tell what a name means.
28+
- Prefer the standard library (containers, algorithms, `std::string`) over hand-rolled equivalents.
1829

1930
## Overall Performance
2031

21-
TODO:
32+
- **Measure before you optimize.** Use a profiler to find the real hot spots instead of guessing; premature optimization wastes effort and harms readability.
33+
- **Avoid unnecessary copies.** Pass large objects by `const&`, or take by value and `std::move` when you need a copy anyway; `reserve()` containers when the final size is known.
34+
- **Let the compiler help.** Return local objects by value and rely on (guaranteed) copy elision rather than returning via output parameters.
35+
- Prefer move semantics for expensive-to-copy types, and remember that `std::move` is a cast, not an operation.
2236

2337
## Code Security
2438

25-
TODO:
39+
- **Manage resources with RAII.** Wrap every resource (memory, files, locks, sockets) in an object whose destructor releases it.
40+
- **Prefer smart pointers** (`std::unique_ptr`, `std::shared_ptr`) over raw `new`/`delete`; avoid owning raw pointers.
41+
- **Avoid undefined behavior**: no out-of-bounds access, no signed overflow, no use-after-free, no strict-aliasing violations (see §9.5). Sanitizers help detect these.
42+
- Prefer `std::span`, `std::array`, and `.at()` over raw pointers and unchecked indexing when bounds matter, and avoid C-style casts in favor of the named C++ casts.
2643

2744
## Maintainability
2845

29-
TODO:
46+
- Keep functions small and focused on a single responsibility; prefer standard algorithms over hand-written loops to express intent clearly.
47+
- Make interfaces hard to misuse: use strong types and enum classes instead of bare `int`/`bool` flags.
48+
- Write tests, and run them continuously so regressions are caught early.
49+
- Document *why*, not *what*: the code already says what it does.
3050

3151
## Portability
3252

33-
TODO:
53+
- Use fixed-width integer types (`std::int32_t`, etc.) from `<cstdint>` when the exact size matters; do not assume `int` is 32 bits or that `char` is signed.
54+
- Avoid implementation-defined and platform-specific behavior; when you must depend on it, isolate it behind a small abstraction.
55+
- Prefer the standard library over platform-specific APIs (e.g. `<filesystem>`, `<thread>`, `<chrono>`) so the same code builds across platforms.
56+
- When byte order matters, query it explicitly (`std::endian` in C++20) rather than assuming little- or big-endian.
3457

3558
[Table of Content](./toc.md) | [Previous Chapter](./appendix1.md)
3659

book/zh-cn/appendix2.md

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,54 @@ order: 12
66

77
# 附录 2:现代 C++ 的最佳实践
88

9-
这篇附录我们来简单谈一谈现代 C++ 的最佳实践。总的来说,笔者关于 C++ 的最佳实践相关的思考主要吸收自[《Effective Modern C++》](https://www.amazon.cn/dp/B016OFO492/ref=sr_1_3?ie=UTF8&qid=1525613457&sr=8-3&keywords=Effective+C%2B%2B)[《C++ 风格指南》](http://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/contents/)。在这篇附录里将简单讨论、并使用实际例子来阐明的方法,介绍一些笔者**个人的****不是随处可见的****非常识性**的最佳实践,并如何保证代码的整体质量
9+
这篇附录我们来简单谈一谈现代 C++ 的最佳实践。这里的许多思考主要吸收自[《Effective Modern C++》](https://www.amazon.cn/dp/B016OFO492/)[《C++ 风格指南》](http://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/contents/),以及由 Bjarne Stroustrup 与 Herb Sutter 维护的 [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)。本附录旨在总结一些被广泛认可的最佳实践,帮助你保证代码的整体质量
1010

1111
## 常用工具
1212

13-
TODO:
13+
优秀的工具能在问题进入生产环境之前就将其拦截:
14+
15+
- **开启警告,并将其视为错误。** 使用 `-Wall -Wextra`(也可考虑 `-Wpedantic`)进行编译;`-Werror` 可以避免警告不断累积。
16+
- **在测试时运行各类消毒器 (sanitizer)。** AddressSanitizer(`-fsanitize=address`)、UndefinedBehaviorSanitizer(`-fsanitize=undefined`)与 ThreadSanitizer(`-fsanitize=thread`)能够在运行期捕获内存错误、未定义行为以及数据竞争。
17+
- **自动格式化与静态检查。** `clang-format` 保证风格一致,`clang-tidy` 则能发现易错模式并给出现代化改写建议。
18+
- **使用现代构建系统与包管理器**,例如 CMake 搭配 vcpkg 或 Conan,让构建可复现。
19+
- **快速实验**:借助 [Compiler Explorer](https://godbolt.org/) 查看生成的汇编,并对比不同编译器与标准版本的行为。
1420

1521
## 代码风格
1622

17-
TODO:
23+
一致的代码风格能让代码库更易于阅读与维护:
24+
25+
- 选定一份风格指南并在整个项目中始终如一地遵循;一致性本身比具体如何选择更重要。
26+
- 坚持 `const` 正确性:只要变量、成员函数或参数无需修改状态,就将其标记为 `const`
27+
- 使用 `auto` 来避免冗余地书写类型,但不要以牺牲可读性为代价——要让读者依然能够看懂名字的含义。
28+
- 优先使用标准库(容器、算法、`std::string`)而非自行实现的等价物。
1829

1930
## 整体性能
2031

21-
TODO:
32+
- **先测量,再优化。** 使用性能分析器找出真正的热点,而不是凭猜测;过早优化既浪费精力又损害可读性。
33+
- **避免不必要的拷贝。**`const&` 传递大对象;当确实需要一份拷贝时,可按值接收再 `std::move`;在已知最终大小时对容器调用 `reserve()`
34+
- **让编译器帮你。** 按值返回局部对象并依赖(强制的)复制消除,而不是通过输出参数返回。
35+
- 对拷贝代价高昂的类型优先使用移动语义,并记住 `std::move` 只是一次类型转换,而非真正的「移动」操作。
2236

2337
## 代码安全
2438

25-
TODO:
39+
- **用 RAII 管理资源。** 把每一种资源(内存、文件、锁、套接字)都封装进一个析构时会释放它的对象中。
40+
- **优先使用智能指针**`std::unique_ptr``std::shared_ptr`)而非裸 `new`/`delete`;避免持有所有权的裸指针。
41+
- **避免未定义行为**:不要越界访问、不要有符号溢出、不要释放后使用、不要违反严格别名规则(参见 §9.5)。消毒器有助于检测这些问题。
42+
- 当边界很重要时,优先使用 `std::span``std::array``.at()` 而非裸指针和不做检查的下标;并用具名的 C++ 类型转换替代 C 风格转换。
2643

2744
## 可维护性
2845

29-
TODO:
46+
- 让函数保持短小、职责单一;优先使用标准算法而非手写循环,以清晰地表达意图。
47+
- 让接口难以被误用:使用强类型与枚举类,而非裸的 `int`/`bool` 标志。
48+
- 编写测试并持续运行,以便尽早发现回归。
49+
- 注释要解释「为什么」,而非「做了什么」:代码本身已经说明了它在做什么。
3050

3151
## 可移植性
3252

33-
TODO:
53+
- 当确切的大小很重要时,使用 `<cstdint>` 中的定宽整数类型(如 `std::int32_t`);不要假设 `int` 是 32 位,也不要假设 `char` 是有符号的。
54+
- 避免依赖实现定义的、平台相关的行为;当不得不依赖时,将其隔离在一层小小的抽象之后。
55+
- 优先使用标准库而非平台特定的 API(例如 `<filesystem>``<thread>``<chrono>`),让同一份代码可以跨平台构建。
56+
- 当字节序很重要时,显式地查询它(C++20 的 `std::endian`),而不是假设是小端或大端。
3457

3558
[返回目录](./toc.md) | [上一章](./11-appendix1.md)
3659

0 commit comments

Comments
 (0)