C++ Core Guidelines 整理目录
- 哲学部分
- 接口(Interface)部分
- 函数部分
- 类和类层次结构部分
- 枚举部分
- 资源管理部分
资源管理规则
R.1: Manage resources automatically using resource handles and RAII (Resource Acquisition Is Initialization)
- 翻译: 使用资源句柄和 RAII 自动管理资源.
- 原因: 确保资源在对象生命周期内得到妥善管理和释放, 避免内存泄漏和其他资源管理问题.
R.2: In interfaces, use raw pointers to denote individual objects (only)
- 翻译: 在接口中使用原始指针仅表示单个对象.
- 原因: 明确指出函数或方法参数仅为指向对象的引用, 并不涉及所有权转移, 防止不必要的复杂性和错误.
R.3: A raw pointer (a T*
) is non-owning
- 翻译: 原始指针(
T*
)是非拥有的. - 原因: 强调原始指针不负责所指向对象的生命周期管理, 有助于清晰地界定责任, 减少内存管理错误.
R.4: A raw reference (a T&
) is non-owning
- 翻译: 原始引用(T&)是非拥有的.
- 原因: 类似于原始指针, 原始引用也不拥有其所引用的对象, 帮助明确代码中各部分的责任界限.
R.5: Prefer scoped objects, don’t heap-allocate unnecessarily
- 翻译: 优先使用作用域内的对象, 避免不必要的堆分配.
- 原因: 减少手动管理内存的需求, 提高程序的安全性和性能, 简化内存管理逻辑.
R.6: Avoid non-const
global variables
- 翻译: 避免非
const
全局变量. - 原因: 全局变量可能会导致难以维护的状态变化, 影响程序的稳定性和可预测性, 使用常量或局部变量替代可以提高代码质量.
分配和释放规则
R.10: Avoid malloc()
and free()
- 翻译: 避免使用
malloc()
和free()
. - 原因: C++提供了更安全和高效的内存管理机制, 如
new
和delete
, 以及智能指针. 使用malloc()
和free()
可能导致类型不匹配和资源泄漏问题.
R.11: Avoid calling new
and delete
explicitly
- 翻译: 尽量不要显式调用
new
和delete
. - 原因: 显式的内存分配和释放容易出错, 且不易于管理. 推荐使用智能指针(如
unique_ptr
或shared_ptr
)自动管理对象生命周期, 减少手动管理内存的需求.
R.12: Immediately give the result of an explicit resource allocation to a manager object
- 翻译: 显式资源分配的结果应立即交给一个管理对象.
- 原因: 确保资源在分配后立刻由一个负责的对象进行管理, 避免资源泄露, 并简化资源管理逻辑.
R.13: Perform at most one explicit resource allocation in a single expression statement
- 翻译: 单个表达式语句中最多进行一次显式资源分配.
- 原因: 限制单个表达式中的显式资源分配次数有助于保持代码的清晰性和可维护性, 降低复杂度并减少错误的发生几率.
R.14: Avoid []
parameters, prefer span
- 翻译: 避免使用
[]
参数, 更倾向于使用span
. - 原因: 使用
std::span
代替传统的数组参数传递方式, 可以提供更安全, 更灵活的数据访问方法, 同时保留原始数组的连续性和效率优势.
R.15: Always overload matched allocation/deallocation pairs
- 翻译: 总是重载匹配的分配/释放对.
- 原因: 当自定义类需要进行内存管理时, 确保为每一种类型的分配操作都有相应的释放操作, 这样可以保证内存管理的一致性和安全性, 避免内存泄漏或其他资源管理问题.
智能指针规则
R.20: Use unique_ptr
or shared_ptr
to represent ownership
- 翻译: 使用
unique_ptr
或shared_ptr
来表示所有权. - 原因: 明确对象的所有权关系, 避免手动管理内存带来的复杂性和潜在错误.
unique_ptr
用于独占所有权, 而shared_ptr
用于共享所有权.
R.21: Prefer unique_ptr
over shared_ptr
unless you need to share ownership
- 翻译: 除非需要共享所有权, 否则优先使用
unique_ptr
. - 原因:
unique_ptr
提供了更高效, 更简单的所有权管理方式, 只有在确实需要共享对象时才使用shared_ptr
.
R.22: Use make_shared()
to make shared_ptr
s
- 翻译: 使用
make_shared()
创建shared_ptr
. - 原因:
make_shared()
不仅简化了代码, 还能通过减少分配次数提高性能, 并确保线程安全.
R.23: Use make_unique()
to make unique_ptr
s
- 翻译: 使用
make_unique()
创建unique_ptr
. - 原因:
make_unique()
提供了一种安全且简洁的方式来创建unique_ptr
, 避免了显式调用new
带来的风险.
R.24: Use std::weak_ptr
to break cycles of shared_ptr
s
- 翻译: 使用
std::weak_ptr
打破shared_ptr
循环引用. - 原因: 防止由于循环引用导致的对象无法释放, 从而引起内存泄漏问题.
weak_ptr
可以观察但不增加引用计数.
R.30: Take smart pointers as parameters only to explicitly express lifetime semantics
- 翻译: 只有为了明确表达生命周期语义时, 才将智能指针作为参数传递.
- 原因: 确保函数或方法的参数清晰地表明对象的生命周期管理意图, 避免不必要的复杂性.
R.31: If you have non-std
smart pointers, follow the basic pattern from std
- 翻译: 如果你使用非标准库的智能指针, 请遵循标准库的基本模式.
- 原因: 确保自定义智能指针的行为与标准库保持一致, 便于理解和维护.
R.32: Take a unique_ptr<widget>
parameter to express that a function assumes ownership of a widget
- 翻译: 使用
unique_ptr<widget>
参数表示函数接管一个widget
的所有权. - 原因: 清晰地表明函数接收并接管对象的所有权, 避免所有权不明确的问题.
R.33: Take a unique_ptr<widget>&
parameter to express that a function reseats the widget
- 翻译: 使用
unique_ptr<widget>&
参数表示函数重新设置widget
的所有权. - 原因: 允许函数修改传入的
unique_ptr
, 以便在函数内部改变其指向的对象.
R.34: Take a shared_ptr<widget>
parameter to express shared ownership
- 翻译: 使用
shared_ptr<widget>
参数表示共享所有权. - 原因: 表明多个对象或函数共同拥有该资源, 确保资源的生命周期由所有者共同管理.
R.35: Take a shared_ptr<widget>&
parameter to express that a function might reseat the shared pointer
- 翻译: 使用
shared_ptr<widget>&
参数表示函数可能会重新设置共享指针. - 原因: 允许函数修改传入的
shared_ptr
, 以便在函数内部改变其指向的对象或调整引用计数.
R.36: Take a const shared_ptr<widget>&
parameter to express that it might retain a reference count to the object ???
- 翻译: 使用
const shared_ptr<widget>&
参数表示可能保留对对象的引用计数. - 原因: 在不需要修改共享指针的情况下, 尽量使用常量引用以减少不必要的拷贝操作, 同时维持引用计数.
R.37: Do not pass a pointer or reference obtained from an aliased smart pointer
- 翻译: 不要传递从别名智能指针获得的指针或引用.
- 原因: 避免因别名智能指针引起的混淆和潜在的生命周期管理问题, 确保每个对象的所有权关系清晰明确.