【C++代码整洁之道】第五章 现代C++的高级概念

文章目录

      • [1. 资源管理](#1. 资源管理)
      • [2. Move语义](#2. Move语义)
      • [3. 编译器是你的搭档](#3. 编译器是你的搭档)
      • [4. 不允许未定义的行为](#4. 不允许未定义的行为)
      • [5. Type-Rich编程](#5. Type-Rich编程)
      • [6. 了解你使用的库](#6. 了解你使用的库)
      • [7. 恰当的异常和错误处理机制](#7. 恰当的异常和错误处理机制)

《C++代码整洁之道》学习笔记,系列之五:现代C++的高级概念

1. 资源管理

  • (1)RAII = Resource Acquisition is Initialization,资源申请即初始化
  • (2)智能指针
    • a) std::unique_ptr 独占资源,不允许调用其拷贝构造函数,可以使用Move语义转移资源
    • b) std::shared_ptr 共享资源,可以拷贝,也可以使用Move语义移动它使用的资源
    • c) std::weak_ptr 不增加引用计数,使用expired()函数检查资源是否有效,使用资源时必须调用lock()函数获取std::shared_ptr实例;std::weak_ptr的存在区分了资源的所有者和使用者;处理两个shared_ptr的循环依赖问题,两个类中的std::shared_ptr成员变量类型替换为std::weak_ptr类型就能解决内存泄漏问题
  • (3)避免显示调用new和delete,通过栈内存、智能指针、库容器等措施来避免

2. Move语义

  • (1)右值引用
    • C++11的Move语义与右值引用紧密相连,右值引用使定位右值的内存位置成为可能
  • (2)零原则:在实现类的时候,应该不需要声明/定义析构函数,也不需要声明/定义
    • copy/move构造函数和copy/move赋值运算符。用智能指针和标准库类来管理资源

3. 编译器是你的搭档

  • (1)auto实现自动类型推导,即类型推导
    • ① auto, const auto, auto&, const auto&
    • ② 不要害怕过多的使用auto,因为绝大多数情况下,auto关键字能提高代码的可读性,重复显而易见的类型违反了DRY原则;所以在不产生歧义的情况下,尽量使用auto关键字
  • (2)c++14 之后支持函数的返回值自动类型推导
  • (3)在模板中也能使用constexpr ,即模板变量。是一种很好的替换宏定义变量 的方法
    类的构造函数和成员函数也可以定义为constexpr类型

4. 不允许未定义的行为

  • (1)避免未定义的行为,程序可能会崩溃

5. Type-Rich编程

  • (1)相信类型,要使用Momentum 这样的类型,而不是没有明确单位的浮点类型double,由于不能类型要匹配,因此结果也更加安全,而不是随便一个double都能使用,比如可能单位不同的double类型
  • (2)这样做的好处是,类型安全在编译期间即得到保障
  • (3)文字操作符:类似Time time = 3.0_s或者Force force = 30.0_N被称为用户自定义字面值,字面值受到保护,必须传递相匹配的字面值,否则会报错,增加安全性

6. 了解你使用的库

  • (1)合格的软件开发者应该知道必要的库或者框架,没有必要重复造轮子。其实就是要用标准的库函数
  • (2)比如std::reverse是一个函数模板,普遍适用于序列容器/关联容器/string和基本数组
  • (3)c++11之前需要借助第三方库才能实现多线程,从c++11开始标准库能支持多线程和并行编程
  • (4)代码的可读性是我们的首要目标之一,另外,源代码注释是一种不好的风格,使用有意义的名称
  • (5)Boost库很强大且一部分已经被c++语言标准接受,但并不完全兼容,比如std::thread和boost::thread还是有一些区别的(线程取消),Boost库不支持std::async等
  • (6)除了STL标准库/和Boost库,还有一些库也值得了解,如日期时间库,正则表达式库,文件系统库,Range-v3库的range::sort,并发数据结构libcds用于高性能并行计算

7. 恰当的异常和错误处理机制

  • (1)对错误和不可预测异常的特殊处理及响应,对于每个软件系统来说都是必要的
  • (2)有四种安全级别,分别是
    • 无异常安全:永远不应该提供这个级别的异常安全
    • 基本异常安全:代码至少能够保证的,也是默认的异常安全级别
    • 强异常安全:异常情况下,数据完全恢复到调用函数之前;在绝对需要的情况下才提供强异常安全保证
    • 保证不抛出异常 :也被称为故障透明性 。不抛出任何异常,问题在内部都得到处理。有一些保证/明确建议不能抛出异常的情况
      *
      1. 任何情况下类的析构函数必须保证不抛出异常
        1. move操作应该保证不抛出异常
        1. 默认构造函数最好不抛出异常
        1. 在任何情况下,swap函数必须保证不抛出异常
  • (3)函数noexcept声明符表示函数不能抛出任何异常,noexcept(true)同理;noexcept(false)表明函数可能抛出异常
    • ① void nonThrowFunction() noexcept;
    • ② noexcept是接口语义的一部分;noexcept可以被编译器优化
  • (4)异常应该用在真正需要异常的情形。对于你束手无策,而且没有办法处理的异常。即仅在非常特殊的情况下抛出异常,不要滥用异常机制来控制正确的程序流程。
  • (5)如果遇到异常导致不能恢复,通常是写日志 记录,或者生成crash dump文件稍后分析,然后立即终止程序。
  • (6)如果try块之后提供多个catch子句,例如区分不同类型的异常,catch子句要按照它们出现的顺序依次执行,而且更具体的异常类型必须在前面,否则会被一般的异常类型隐藏。

·


【参考文章】

[1]. C++代码整洁之道

相关推荐
爱跑步的一个人1 小时前
STL-常用排序算法
开发语言·c++·排序算法
星光樱梦1 小时前
24. 正则表达式
c++
fathing1 小时前
c# 调用c++ 的dll 出现找不到函数入口点
开发语言·c++·c#
hope_wisdom2 小时前
C++网络编程之SSL/TLS加密通信
网络·c++·ssl·tls·加密通信
erxij2 小时前
【游戏引擎之路】登神长阶(十四)——OpenGL教程:士别三日,当刮目相看
c++·经验分享·游戏·3d·游戏引擎
林开落L3 小时前
前缀和算法习题篇(上)
c++·算法·leetcode
Prejudices3 小时前
C++如何调用Python脚本
开发语言·c++·python
单音GG3 小时前
推荐一个基于协程的C++(lua)游戏服务器
服务器·c++·游戏·lua
qing_0406033 小时前
C++——多态
开发语言·c++·多态
孙同学_3 小时前
【C++】—掌握STL vector 类:“Vector简介:动态数组的高效应用”
开发语言·c++