好记性不如铅笔头

C && C++, C++ STL, 编程

C++ STL读书笔记:stl_construct.h

CONTENTS

备注:

本读书笔记基于侯捷先生的《STL源码剖析》,截图和注释版权均属于原作者所有。
本读书笔记中的源码部分直接拷贝自SGI-STL,部分代码删除了头部的版权注释,但代码版权属于原作者
小弟初看stl,很多代码都不是太懂,注释可能有很多错误,还请路过的各位大牛多多给予指导。

stl_construct.h

主要用于封装各种构造与析构函数,部分源码如下(为了节省版面,删除了头部的版权注释):

#ifndef _STL_CONSTRUCT_H
#define _STL_CONSTRUCT_H 1

//这里包含了new,后面便可以使用placement new,new文件源码后面附上。
#include <new>
#include <bits/move.h>

//在std命名空间中
_GLIBCXX_BEGIN_NAMESPACE(std)

  /**
   * Constructs an object in existing memory by invoking an allocated
   * object's constructor with an initializer.
   */
   //新实例的内存已经申请好了,这里调用构造函数将其构造好。
  template<typename _T1, typename _T2>
    inline void
#ifdef __GXX_EXPERIMENTAL_CXX0X__
    // Allow perfect forwarding
    _Construct(_T1* __p, _T2&& __value)
#else
    _Construct(_T1* __p, const _T2& __value)
#endif
    {
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 402. wrong new expression in [some_]allocator::construct
      ::new(static_cast<void*>(__p)) _T1(_GLIBCXX_FORWARD(_T2, __value));
      //placement new,可简单的理解为 _T1(__value); 
    }

  /**
   * Destroy the object pointed to by a pointer type.
   */
  //析构单个实例
  //只有一个入参,直接调用实例的析构函数。
  template<typename _Tp>
    inline void
    _Destroy(_Tp* __pointer)
    { __pointer->~_Tp(); }

 //有两个参数,分别是头尾部[)的iterator,通过iterator的累加,分别调用一个入参的_Destroy函数进行析构
 //此版本的_Destroy_aux是需要【显式的】调用析构函数的。
  template<bool>
    struct _Destroy_aux
    {
      template<typename _ForwardIterator>
        static void //这里使用的是static void,这样便可以直接通过类名来调用了_Destroy_aux::,非常方便
        __destroy(_ForwardIterator __first, _ForwardIterator __last)
 {
   for (; __first != __last; ++__first)
     std::_Destroy(&*__first);
 }
    };

//同上,
//此版本的_Destroy_aux是【不需要】调用析构函数的。个人的理解是如果实例比较简单,不需要显示的调用析构函数,
//那么可以进行流程的优化,省略掉调用析构函数的流程,提高运行效率。
  template<>
    struct _Destroy_aux<true>
    {
      template<typename _ForwardIterator>
        static void
        __destroy(_ForwardIterator, _ForwardIterator) { }
    };

  /**
   * Destroy a range of objects.  If the value_type of the object has
   * a trivial destructor, the compiler should optimize all of this
   * away, otherwise the objects' destructors must be invoked.
   */
//析构多个实例,2参数版本
//这里首先对是否需要调用析构函数进行判断,如果实例比较简单(比如没有动态内存的申请),析构时无需显示调用析构函数(比如类定义时析构函数就未实现)。
//就可以进行代码优化(调用_Destroy_aux的不同版本)。
  template<typename _ForwardIterator>
    inline void
    _Destroy(_ForwardIterator __first, _ForwardIterator __last)
    {
      typedef typename iterator_traits<_ForwardIterator>::value_type
                       _Value_type;
      std::_Destroy_aux<__has_trivial_destructor(_Value_type)>::
 __destroy(__first, __last);
    }

  /**
   * Destroy a range of objects using the supplied allocator.  For
   * nondefault allocators we do not optimize away invocation of 
   * destroy() even if _Tp has a trivial destructor.
   */
//如果实例不是通过默认的allocator,而是通过其他的自定义的allocator来申请的,那么在析构时就不能调用默认的析构函数了
//就必须使用自定义的allocator的析构函数,上面的注释也提到了这一点。
  template <typename _Tp> class allocator;
  template<typename _ForwardIterator, typename _Allocator>
    void
    _Destroy(_ForwardIterator __first, _ForwardIterator __last,
      _Allocator& __alloc)
    {
      for (; __first != __last; ++__first)
 __alloc.destroy(&*__first);
    }

//如果调用模板函数时显式的提到了allocator,但不是自定义版本的,那么底层的实现依然是默认的allocator。
//直接调用2参数版本。
  template<typename _ForwardIterator, typename _Tp>
    inline void
    _Destroy(_ForwardIterator __first, _ForwardIterator __last,
      allocator<_Tp>&)
    {
      _Destroy(__first, __last);
    }

_GLIBCXX_END_NAMESPACE
#endif /* _STL_CONSTRUCT_H */

new

文件部分源码如下(为了节省版面,删除了头部的版权注释):

#ifndef _NEW
#define _NEW

#pragma GCC system_header

#include <cstddef>
#include <exception>

#pragma GCC visibility push(default)

extern "C++" {

namespace std 
{
  /**
   *  @brief  Exception possibly thrown by @c new.
   *  @ingroup exceptions
   *
   *  @c bad_alloc (or classes derived from it) is used to report allocation
   *  errors from the throwing forms of @c new.  */


  //声明了一个【 bad_alloc 】异常类,用来在new/delete失败时抛出
  class _GLIBCXX_IMPORT bad_alloc : public exception
  {
  public:
    bad_alloc() throw() { }

    // This declaration is not useless:
    // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
    virtual ~bad_alloc() throw();


    // See comment in eh_exception.cc.
    virtual const char* what() const throw();
  };

  struct nothrow_t { };

  extern const nothrow_t nothrow;

  /** If you write your own error handler to be called by @c new, it must
   *  be of this type.  */
  typedef void (*new_handler)();

  /// Takes a replacement handler as the argument, returns the
  /// previous handler.
  new_handler set_new_handler(new_handler) throw();
} // namespace std

//@{
/** These are replaceable signatures:
 *  - normal single new and delete (no arguments, throw @c bad_alloc on error)
 *  - normal array new and delete (same)
 *  - @c nothrow single new and delete (take a @c nothrow argument, return
 *    @c NULL on error)
 *  - @c nothrow array new and delete (same)
 *
 *  Placement new and delete signatures (take a memory address argument,
 *  does nothing) may not be replaced by a user's program.
*/


//各种重载 new/delete 运算符声明
void* operator new(std::size_t) throw (std::bad_alloc);
void* operator new[](std::size_t) throw (std::bad_alloc);
void operator delete(void*) throw();
void operator delete[](void*) throw();
void* operator new(std::size_t, const std::nothrow_t&) throw();
void* operator new[](std::size_t, const std::nothrow_t&) throw();
void operator delete(void*, const std::nothrow_t&) throw();
void operator delete[](void*, const std::nothrow_t&) throw();

//Placement new 和 Placement delete 函数,实现的非常简单
// Default placement versions of operator new.
inline void* operator new(std::size_t, void* __p) throw() { return __p; }
inline void* operator new[](std::size_t, void* __p) throw() { return __p; }


// Default placement versions of operator delete.
inline void  operator delete  (void*, void*) throw() { }
inline void  operator delete[](void*, void*) throw() { }
//@}
} // extern "C++"

#pragma GCC visibility pop
#endif

发表评论

7 + 4 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据