0%

C++:资源管理和对象的基本原则

资源管理和对象的基本原则

C++的特点与演化

  1. 为什么要使用C++?
    1. 贴近硬件:
      • 使用原生的指令和类型,高性能
      • 方便使用硬件(GPU、FPGA等)
    2. 零开销抽象
      • 类、继承、模板
      • 零开销!=无开销, 零开销=无额外开销
  2. C和C++
    1. 功能上,C++是C的超集
    2. C++更加严格和安全,比如说const的正确性、指针的自动转换
    3. 现代C++的惯用法和C大相径庭
      • C和机器码有更简单的映射关系,从C源码可以大致知道机器码是什么样
      • C++里有更多的抽象机制,源代码和机器码映射复杂得多

资源管理和对象的基本原则

1. 堆与栈

栈的示例

main对应的x86汇编代码(msvc)

  1. 设置栈框架:保存原有的ebp的值,设置新的ebp的值,ebp的作用:索引这个函数所用到的参数和本地变量
  2. 参数压栈
  3. call:调用bar函数,名字奇怪的原因:编译器会起名
  4. 退栈:esp的指针+4——pop eax:取出数据,ESP指向栈中下一个元素
  5. 异或操作对eax寄存器清零,函数返回值存储在eax寄存器

bar对应的x86汇编代码(msvc)

调用过程中的栈变化

“返回main的地址”:main下一句指令的地址

栈内存的特性:

  1. 分配简单,只是移动栈指针
  2. 当前函数执行完即自动释放
  3. 后进先出,不可能出现内存碎片
  4. 函数返回后,栈上对象即被销毁
  5. 栈内存不分享,栈上对象通常没有多线程竞争问题(除非把指向栈内存的指针传递给另一个线程)

堆内存的特性:

  1. 分配和释放算法较为复杂
  2. 可能出现内存碎片
  3. 内存的分配和释放通常需要加锁
  4. 堆上的对象在被释放之前一直可以使用
  5. 堆上对象可能被多个线程访问,潜在有线程竞争问题

2. RAII

——析构函数和RAII是C++最基本的惯用法

  • RAII:Resource Acquisition Is Initialization

  • 帮助管理堆上的对象:对象很大、对象的大小在编译时不能确定、对象是函数的返回值但由于特殊的原因不应使用对象的值返回

  • newdelete的原理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // new circle(...)
    {
    void *temp=operator new(sizeof(circle)); //分配内存
    try{
    circle *ptr=static_cast<circle*>(temp); //类型转换
    ptr->circle(...); //通过指针调用构造函数
    return ptr;
    }
    catch(...){
    operator delete(ptr);
    throw;
    }
    }
    // delete ptr
    if(ptr!=nullptr){
    ptr->~shape();
    operator delete(ptr);
    }