条例26~30(实现)-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

条例26

尽可能延后变量定义式出现的时间

  • 尽可能的延后定义一个变量因为只要你定义出来哪怕你没有使用也得承受构造和析构成本。假如有异常抛出的情况你定义类一个变量还没有使用的时候就抛出了异常。这个变量就直接调用了析构做了无用功。应当尽可能的延后到使用前一刻为止。例如用拷贝构造代替构造+赋值。
  • 当遇到for循环的时候可以将定义放在循体外面。因为多视情况下n次赋值的情况要好于n次构造。若除非已知构造+析构的成本小于赋值的成本则都应该遵守这种情况

总结

  • 尽可能延后变量定义式的出现这样做能增加效率和可读性

条例27

尽量少做转型动作

  • 有两种旧式类型转换,和四种新式类型转换
    (T)expression    //旧式类型转换
    T(expression)
    
    const_cast<t>    //新式类型转换
    dynamic_cast<t>
    reinterpret_cast<t>
    static_cast<t>
    
    

    const_cast 用于将对象的常量性去处dynamic_cast用于安全向下转型。一般用于父类对象向子类转换reinterpret_cast我叫他万能的强制类型转换不具备可移植性static_cast,用来强迫隐式转换,是非多态类型的转换静态转换编译器隐式执行的任何类型转换都可用static_cast。

  • 尽量使用新式类型转换因为更有辨识度更具有安全性编译器更容易发现代码的错误。

转型动作其实有可能包含代码

  • 比如int转换成float因为双方在内存的存储方式不同所以势必会产生代码。
  • 尤其是当父类指针指向子类对象的时候由于偏移量的存在所以会在运行期间来回跳转

转型有可能导致错误

  • 由于转型动作有可能会产生临时变量若不注意就有可能对临时变量进行了操作就会导致伤残。

dynamic_cast的使用场景

  • dynamic_cast的执行速度本身是很慢的成本很高使用时应注意。
  • 通常在拥有一个子类对象却拥有一个父类指针的时候使用这个转型。
  • 我们可以通过两种方法解决这种场景首先可以通过智能指针操作这样就绕过了接口而使用智能指针进行操作。或者在父类内提供一个接口将virtual函数向继承体系上方移动。

绝对避免连续的dynamic转型

  • 效率极低当有这种场景应该用虚函数解决

总结

  • 尽量避免转型注重效率时尤其避免dynamic转型
  • 若转型是必要的应将其隐藏在函数背后而不用手动调用
  • 尽量使用新式的类型转型

条例28

尽量避免返回引用指向对象内部成分

  • 不能使用引用返回函数体内的局部变量因为局部变量会被销毁这样引用就空悬了
  • 若使用引用返回private成员则会破坏原有的封装性。
  • 不仅仅是引用上述两种情况在指针返回或是迭代器返回也是存在的。
  • 可以同过返回const 引用保持封装性

总结

  • 避免返回引用指针迭代器指向对象内部。这样能增加封装性避免虚调的发生

条款29

为异常安全而努力是值得的

  • 通常有异常安全问题的函数会导致资源泄漏或者数据败坏例如指针悬空等问题。
  • 异常安全函数提供以下三种保证基本承诺异常抛出后任何事物仍然保持有效状态但整体不可预期强烈保证若程序抛出异常程序会恢复到调用 函数之前的状态不抛出异常的保证承诺绝不抛出异常
  • 通常情况下应提供能提供的的最强烈的保证但最常用的是强烈保证和基本承诺两种。
  • 可以采用资源管理类实现异常安全。或者将更改元素的操作语句放在有可能出现异常语句的后面这样即使抛出异常也不会改变原来的值。

通过采用拷贝复制策略为打算操作的对象创建一个副本然后对副本进行一切修改修改操作成功后再拷贝回给原始的对象。可以很好的实现强烈保证要求的复原操作

  • 通常拷贝复制策略是通过pimpl 手法将所有隶属对象的数据从原对象放进另一个对象副本内然后赋予原对象一个指针指向副本实现的。但这个策略无法保证强烈保证因为假设你在这个策略内调用了别的函数并且这个函数本身不是的异常安全性低于强烈保证这时我们就需要写出代码恢复此函数调用之前的状态。就算该函数是强烈保证也不行假如调用两个函数一个正常执行一个抛出异常就会造成部分更改的问题。
  • 综上有的时候实现强烈保证有时候是不实际的因为本身拷贝复制策略效率就很低。这时就只能提供基本保证。

总结

  • 异常安全函数即使发生异常也不会泄漏资源或者允许任何数据结构破坏通常有三种类型的保证基本型强烈性不抛异常性。
  • 强烈保证往往能够以拷贝复制实现但强烈保证并非对所有函数都具备可实现意义。
  • 函数提供的保证级别是由所调用函数的最低等的异常安全级别决定的

条例30

透彻了解内联函数

  • 内联函数的执行动作像函数同时又不用承受调用函数的开销比宏好很多。
  • 过度使用内联会导致代码体积增大降低指令高速缓存装置的击中率带来效率降低。
  • 内联只是对编译器的一个建议是否实现成内联是由编译器自身决定。对于所有虚函数都无法实现成内联。因为虚函数意味这运行时决定调用哪个函数而内联需要在编译期间替换出函数本体。
  • 大多数内联是在编译器间行为。不是所有类模板都需要定义为内联。
  • 构造和析构往往不适合实现成内联。虽然你以为构造和析构不含代码适合内联但实际上为了确保资源的正确构造和析构同时维护异常安全性编译器会在你的构造和析构函数里加上代码来实现这些功能这就让他们不适合内联。
  • 内联函数意味着不能随着库函数的升级而升级一旦有修改必须重新编译链接。

总结

  • 将大多数内联限制在小型和被频繁调用的函数身上这样能使调试更加容易让潜在的代码膨胀问题最小化提升程序运行速度。
  • 不能因为类模板出现在头文件而将其声明为内联。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6