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
发表评论