• STL源码阅读笔记-对象的构造与析构


    STL 中对象的构造和析构

    在C++中,分配内存的操作一般如下:

    class FOO{...};
    FOO *fp = new FOO;
    .........
    delete fp
    
    • 1
    • 2
    • 3
    • 4

    在new 操作中可以分为两步:

    1. ::operator new 申请内存
    2. 在申请的内存上调用FOO的构造函数构造对象

    而在delete操作中也可以分为两步:

    1. 调用FOO的析构函数
    2. ::operator delete 释放内存

    STL 的 allocator 将几个操作都区分开来,内存申请由 alloc::allocatate() 负责,内存释放由alloc::deallocate()负责。对象的构造由::construct()负责,析构由::destory()负责。

    STL中负责对象构造和析构的全局函数定义在了 中,内容不多,才100行左右的代码

    construct()

    // 开放接口
    template 
    inline void construct(_T1* __p, const _T2& __value) {
      _Construct(__p, __value);
    }
    
    // 开放接口
    template 
    inline void construct(_T1* __p) {
      _Construct(__p);
    }
    
    template 
    inline void _Construct(_T1* __p, const _T2& __value) {
      new ((void*) __p) _T1(__value);
    }
    
    template 
    inline void _Construct(_T1* __p) {
      new ((void*) __p) _T1();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    construct 接口没啥特别的操作,只是将根据传入的参数来选择调用的构造方式。

    destory()

    template 
    inline void destroy(_Tp* __pointer) {
      _Destroy(__pointer);
    }
    
    template 
    inline void destroy(_ForwardIterator __first, _ForwardIterator __last) {
      _Destroy(__first, __last);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    desotry 则分为两种,一种是传入单个对象的指针,另一种则传入一组迭代器。

    template 
    inline void destroy(_Tp* __pointer) {
      _Destroy(__pointer);
    }
    
    template 
    inline void _Destroy(_Tp* __pointer) {
      __pointer->~_Tp();
    }
    
    inline void _Destroy(char*, char*) {}
    inline void _Destroy(int*, int*) {}
    inline void _Destroy(long*, long*) {}
    inline void _Destroy(float*, float*) {}
    inline void _Destroy(double*, double*) {}
    #ifdef __STL_HAS_WCHAR_T
    inline void _Destroy(wchar_t*, wchar_t*) {}
    #endif /* __STL_HAS_WCHAR_T */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    传入当个指针的版本会根据对象的具体类型来决定是否调用特化版本的析构,不存在特化的则统一调用对象的析构函数

    // 开放接口
    template 
    inline void destroy(_ForwardIterator __first, _ForwardIterator __last) {
      _Destroy(__first, __last);
    }
    
    
    template 
    inline void _Destroy(_ForwardIterator __first, _ForwardIterator __last) {
    	// __VALUE_TYPE 取得迭代器所指对象类型
      __destroy(__first, __last, __VALUE_TYPE(__first));
    }
    
    template 
    inline void 
    __destroy(_ForwardIterator __first, _ForwardIterator __last, _Tp*)
    {
      typedef typename __type_traits<_Tp>::has_trivial_destructor
              _Trivial_destructor;
       // 这边会判断这个对象类型是否是trivial 类型
      __destroy_aux(__first, __last, _Trivial_destructor());
    }
    
    
    template 
    void
    __destroy_aux(_ForwardIterator __first, _ForwardIterator __last, __false_type)
    {
      for ( ; __first != __last; ++__first)
        destroy(&*__first);
    }
    
    template  
    inline void __destroy_aux(_ForwardIterator, _ForwardIterator, __true_type) {}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    迭代器版本则会取得迭代器所指的对象类型来判断对象的析构函数是否是traivial 的。 (_Trivial_destructor中是如何做到判断的,书上要在第三章才能知道,这边也还没学习到

    小结

    STL对于对象的构造和析构调用图如下:
    对象的构造与析构

  • 相关阅读:
    【EI会议征稿】2023计算机网络技术与电子信息工程国际学术会议(CNTEIE 2023)
    JVM 入门
    leecode#Excel表列序号#组合两个表
    APK加固技术的演变,APK加固技术和不足之处
    数字图像处理练习题整理 (一)
    7分钟了解ChatGPT是如何运作的
    视频怎么制作动图?分享简单的视频制作gif方法
    计算机毕业设计ssm社区疫情防控系统3j56g系统+程序+源码+lw+远程部署
    SQL并行与否的性能差异
    Linux操作系统的基础IO
  • 原文地址:https://blog.csdn.net/ii0789789789/article/details/126564554