Skip to content
说明
- 规范与建议以Google代码规范为基础, 以Effective系列等作为补充(去掉了重合的, 过时的, 基本可以省略的内容)
- Google代码规范的注释及格式等部分考虑使用cpplint工具来完成
- 版本: 1.0.0
- 最后更新: 2021-09-01 13:01
- 作者: orient
Google代码规范
Effective C++ 3rd
- Item 04. 确定对象被使用前已被初始化
- Item 07. 为多态基类声明virtual析构函数
- Item 09. 绝不在构造函数和析构函数中调用virtual函数
- Item 11. operator=处理好自我赋值
- Item 12. 复制对象时勿忘其每一个成分
- Item 16. 成对使用new和delete要采取相同形式
- Item 21. 绝不返回局部变量(local stack)的指针或引用
- Item 26. 尽可能延后变量定义的出现时间
- Item 28. 避免返回handles(包括引用指针迭代器)指向对象内部
- Item 35. 考虑virtual以外的其它选择 TIPS: 函数指针; std::bind, std::function; CRTP; MFC消息映射表等
- Item 53. 重视编译器警告
More Effective C++
- Item M3. 不要对数组使用多态
- Item M4. 避免无用的缺省构造函数
- Item M5. 谨慎定义类型转换函数
- Item M6. 尽量使用前缀自增自减
- Item M13. 通过引用(reference)捕获异常
- Item M24. 理解虚拟函数、多继承、虚基类和RTTI所需的代价
Effective STL
- 条款04. 用empty来代替检查size()是否为0
- 条款05. 区间成员函数优先于与之对应的单元素成员函数
- 条款09. 慎重选择删除元素的方法
- 条款14. 使用reserve来避免不必要的重新分配
- 条款22. 切勿直接修改set或multiset中的键
- 条款32. 如果确实需要删除元素, 则需要在remove这一类算法之后调用erase
- 条款33. 对包含指针的容器使用remove这一类算法时要特别小心
- 条款44. 容器的成员函数优先于同名的算法
Effective Modern C++
- 类型推导
- Item 1:理解模板类型推导 已修订
- Item 2:理解auto类型推导
- Item 3:理解decltype
- Item 4:学会查看类型推导结果
- auto
- Item 5:优先考虑auto而非显式类型声明
- Item 6:auto推导若非己愿,使用显式类型初始化惯用法
- 移步现代C++
- Item 7:区别使用()和{}创建对象
- Item 8:优先考虑nullptr而非0和NULL
- Item 9:优先考虑别名声明而非typedefs
- Item 10:优先考虑限域枚举而非未限域枚举 已修订
- Item 11:优先考虑使用deleted函数而非使用未定义的私有声明
- Item 12:使用override声明重载函数
- Item 13:优先考虑const_iterator而非iterator
- Item 14:如果函数不抛出异常请使用noexcept
- Item 15:尽可能的使用constexpr
- Item 16:让const成员函数线程安全 由 @windski贡献
- Item 17:理解特殊成员函数函数的生成
- 智能指针
- Item 18:对于独占资源使用std::unique_ptr 由 @wendajiang贡献
- Item 19:对于共享资源使用std::shared_ptr 已修订
- Item 20:当std::shard_ptr可能悬空时使用std::weak_ptr 更新完成
- Item 21:优先考虑使用std::make_unique和std::make_shared而非new 由 @pusidun贡献
- Item 22:当使用Pimpl惯用法,请在实现文件中定义特殊成员函数 由 @BlurryLight贡献
- 右值引用,移动语义,完美转发
- Item 23:理解std::move和std::forward 由 @BlurryLight贡献
- Item 24:区别通用引用和右值引用 由 @BlurryLight贡献
- Item 25:对于右值引用使用std::move,对于通用引用使用std::forward由 @wendajiang贡献
- Item 26:避免重载通用引用 由 @wendajiang贡献
- Item 27:熟悉重载通用引用的替代品 由 @wendajiang贡献
- Item 28:理解引用折叠 由 @wendajiang贡献
- Item 29:认识移动操作的缺点 由 @wendajiang贡献
- Item 30:熟悉完美转发失败的情况 由 @wendajiang贡献
- Lambda表达式
- Item 31:避免使用默认捕获模式 由 @LucienXian贡献
- Item 32:使用初始化捕获来移动对象到闭包中 由 @LucienXian贡献
- Item 33:对于std::forward的auto&&形参使用decltype 由 @LucienXian贡献
- Item 34:优先考虑lambda表达式而非std::bind 由 @LucienXian贡献
- 并发API
- Item 35:优先考虑基于任务的编程而非基于线程的编程 由 @wendajiang贡献
- Item 36:如果有异步的必要请指定std::launch::threads 由 @wendajiang贡献
- Item 37:从各个方面使得std::threads unjoinable 由 @wendajiang贡献
- Item 38:关注不同线程句柄析构行为 由 @wendajiang贡献
- Item 39:考虑对于单次事件通信使用void 由 @wendajiang贡献
- Item 40:对于并发使用std::atomic,volatile用于特殊内存区 由 @wendajiang贡献
- 微调
- Item 41:对于那些可移动总是被拷贝的形参使用传值方式 由 @wendajiang贡献
- Item 42:考虑就地创建而非插入 由 @wendajiang贡献
C++ Coding Standards
- Item004. 在代码审查上投入
- Item039. 考虑将虚拟函数声明为非公用的, 将公用函数声明为非虚拟的(TIPS: 基类析构函数除外)
- Item054. 避免切片
- Item054. 使用赋值的标准形式
- Item060. 要避免在不同的模块中分配和释放内存
- Item061. 不要在头文件中定义具有链接的实体
- Item062. 不要允许异常跨越边界传播
- Item063. 在模块的接口中使用具有良好的可移植性的类型
- Item090. 避免使用类型分支, 多使用多态
- Item096. 不要对非POD进行memcpy/memcmp
内存
- [强制] 禁止使用空指针和悬挂指针(野指针)
- [强制] 严禁两次及以上的free/delete(同时, 应当优先选择智能指针)
- [强制] 防止缓冲区溢出(例如数组越界)
- [建议] 不要重载全局::operator new()等函数
并发
- [建议] 优先使用消息传递而不是共享内存(使用通信来共享内存, 而不是通过共享内存来通信)/尽量无状态/尽量不可变(immutable)状态
- [建议] 优先使用Socket(TCP)
- [建议] 如果必须共享状态, 尽量使用消息队列/任务队列等公用组件
- [建议] 互斥尽量使用Mutex, 并尽量使用非递归锁
- [建议] 深入理解condition-variable
- [建议] 深入理解rwlock
- [建议] 深入理解spinlock
- [建议] 深入理解volatile, 一般情况下不应使用volatile
- [建议] 一般只有基础库才需要使用atomic与memory-order
- [建议] 一般只有基础库才需要使用lock-free, lock-free的正确性应当得到充分验证
- [建议] signal要考虑异步信号安全, 可以考虑libuv的处理方式
- linux async-signal-safe系统函数 http://man7.org/linux/man-pages/man7/signal-safety.7.html
- linux 非线程安全函数 https://man7.org/linux/man-pages/man7/pthreads.7.html
- [建议] 借助工具/库来检测锁缺失, 死锁等并发问题
工具
- cpplint
- [建议] cpplint标准比较严格, 可以保持代码风格的一致性
- [建议] 可以添加少量的filter, 让所有检查通过
- Sanitizer
- cmake
参考