STL源码剖析 内存基本处理工具 初始化空间的五个函数

53 篇文章 1 订阅
31 篇文章 2 订阅
  • 初始化空间的五个函数
  • 构造函数 construct()
  • 析构函数 destroy()
  • 剩余三个底层函数 和 高层函数之间的对应关系如下
  • uninitialized_copy()  对应 copy()
  • uninitialized_fill()  对应 fill()
  • uninitialized_fill_n()  对应 fill_n()
  • 使用<memory>使用上述三个底层函数

uninitialized_copy()

template<class InputIterator,class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first,InputIterator last,ForwardIterator result);
  • uninitialized_copy() 将内存的配置和对象的构造行为分离开来
  • 如果指向的输出区域[result ,result+(last - first)] 内的每一个迭代器都指向的是未经初始化的区域,那么uninitialized_copy()会使用copy constructor,给身为输入来源的[first , last] 范围内的每一个对象产生一个复制品,放到输出范围内
  • 针对输入范围内的每一个迭代器i 使用construct(&*(result + (i-first)),*i) 产生*i的复制品,放置到输出范围的相对位置上

容器的全局间构造函数 通过两个步骤完成

  • 配置内存块  足以包含范围内的所有元素
  • 使用uninitialized_copy()在这个范围上构造元素

注意事项

  • 原子性;commit or rollback
  • 要不给所有元素都全部执行构造函数,要不不构造任何东西,必须析构已经产生的所有元素
//如果是copy construction 等同于assignment而且destructor 是 trivial以下就会有效
//如果是POD型别 执行的流程就会跳转到以下函数,这个是通过function template的参数推导机制得到的
template<class InputIterator,class ForwardIterator>
inline ForwardIterator __uninitialized_copy_aux(InputIterator first,InputIterator last,
                                                ForwardIterator result,true_type){
    return copy(first,last,result);//调用STL算法 copy()
}
//如果不是POD型别 执行的流程就会转向以下函数  这个是通过function template的参数推导机制得到的
template<class InputIterator,class ForwardIterator>
inline ForwardIterator __uninitialized_copy_aux(InputIterator first,InputIterator last,
                                                ForwardIterator result,false_type){
    ForwardIterator cur = result;
    //为了简化 省略了异常处理
    for(; first!=last;++first,++cur){
        Chy::_allocate(&*cur,*first);
    }
    return cur;
}

//函数的逻辑是
//首先萃取出 迭代器first的value type,然后判断这个型别是否是POD类型
template<class InputIterator,class ForwardIterator,class T>
inline ForwardIterator __uninitizlized_copy(ForwardIterator first,ForwardIterator last,ForwardIterator result,T*){
    //以下使用的是__type_traits<T1>::is_POD_type is _POD
    typedef typename __type_traits<T>::is_POD_type is_POD;
    return (__uninitialized_copy_aux(first,last,result,is_POD()));
}

/*
 * 迭代器first指向的是 输入端的起始位置
 * 迭代器last指向的是 输入端的结束位置
 * 迭代器result指向的是 输出端的(初始化)的起始位置
 */
template<class InputIterator,class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first,InputIterator last,ForwardIterator result){

}

//针对 char* 和wchar*两种型别 采用最有效率的做法 memmove(直接移动内存内存执行复制的行为)
//偏特化设计
//针对const char*的特化版本

inline char* uninitialized_copy(const char* first,const char* last,char* result){
    memmove(result,first,last-first);
    return result+(last - first);
}

//针对const wchar_t *的特化版本
inline wchar_t* uninitialized_copy(const wchar_t* first,const wchar_t* last,wchar_t* result){
    memmove(result,first,sizeof(wchar_t)*(last - first));
    return result + (last - first);
}

uninitialized_fill()

template<class ForwardIterator,class T>
ForwardIterator uninitialized_fill(ForwardIterator first,ForwardIterator last,const T&x);
  • uninitialized_fill() 将内存的配置和对象的构造行为分离开来
  • 如果指向的输出区域[first,last] 内的每一个迭代器都指向的是未经初始化的区域,那么uninitialized_fill()会在这个范围内产生x(上述第三个参数的复制品)
  • 即uninitialized_fill()会针对[first,last]范围内的每个迭代器i 调用construct(&*i,x),在i所指定的地方产生i的复制品。

注意事项

  • 原子性;commit or rollback
  • 要不给所有元素都全部执行构造函数,要不不构造任何东西,必须析构已经产生的所有元素
//如果是copy construction 等同于assignment而且destructor 是 trivial以下就会有效
//如果是POD型别 执行的流程就会跳转到以下函数,这个是通过function template的参数推导机制得到的
template <class ForwardIterator,class T>
inline void __uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
                                     const T& x,true_type){
    fill(first,last,x);//调用STL算法 fill()
}
//如果不是POD型别 执行的流程就会转向以下函数  这个是通过function template的参数推导机制得到的
template <class ForwardIterator,class T>
inline void __uninitialized_fill_aux(ForwardIterator first,ForwardIterator last,
                                     const T& x,false_type){
    ForwardIterator cur = first;
    //为了简化 省略了异常处理
    for(;cur != last;++cur){
        Chy::_construct(&*cur,x);
    }
}

template<class ForwardIterator,class T,class T1>
inline void __uninitialized_fill(ForwardIterator first,ForwardIterator last,
                                 const T&x,T1*){
    typedef typename __type_traits<T1>::is_POD_type is_POD;
    __uninitialized_fill_aux(first,last,x,is_POD());
}

/*
 * 迭代器first指向输出端 (欲初始化空间) 起始处
 * 迭代器last指向的输出端 (欲初始化空间) 结尾处 前闭后开区间
 * x 表示初始数值
 */
template<class ForwardIterator,class T>
ForwardIterator uninitialized_fill(ForwardIterator first,ForwardIterator last,const T&x){
    __uninitialized_fill(first,last,x,value_type(first));
}

uninitialized_fill_n()

template<class ForwardIterator,class Size,class T>
ForwardIterator uninitialized_fill_n(ForwardIterator first,Size n,const T&x);
  • uninitialized_fill_n() 将内存的配置和对象的构造行为分离开来
  • 如果指向的输出区域[first,first+n] 内的每一个迭代器都指向的是未经初始化的区域,那么uninitialized_fill()会在这个范围内产生x(上述第三个参数的复制品)
  • 即uninitialized_fill()会针对[first,last]范围内的每个迭代器i 调用construct(&*i,x),在i所指定的地方产生i的复制品。
  • 原子性;commit or rollback
  • 要不给所有元素都全部执行构造函数,要不不构造任何东西,必须析构已经产生的所有元素

补充

  • POD类型是指 Plain Old Data,也就是标量类型或者传统的C struct型别
  • POD类型 必然具备trivial ctor/dtor/copy/assignment函数
  • 因此对于POD型别采用最有效率的初值填写手法,对于non POD型别采取最保险安全的做法
//如果是copy construction 等同于assignment而且destructor 是 trivial以下就会有效
//如果是POD型别 执行的流程就会跳转到以下函数,这个是通过function template的参数推导机制得到的
template<class ForwardIterator,class Size,class T>
inline ForwardIterator __uninitizlized_fill_n_aux(ForwardIterator first,Size n,const T&x){
    return fill_n(first,n,x); //交给高阶函数执行
}

//如果不是POD型别 执行的流程就会转向以下函数  这个是通过function template的参数推导机制得到的
template<class ForwardIterator,class Size,class T>
inline ForwardIterator __uninitizlized_fill_n_aux(ForwardIterator first,Size n,const T&x,false_type){
    ForwardIterator cur = first;
    //为了简化 省略了异常处理
    for( ; n>0 ; --n,++cur){
        Chy::_allocate(&*cur,x);
    }
    return cur;
}

//函数的逻辑是
//首先萃取出 迭代器first的value type,然后判断这个型别是否是POD类型
template<class ForwardIterator,class Size,class T,class T1>
inline ForwardIterator __uninitizlized_fill_n(ForwardIterator first,Size n,const T&x,T1*){
    //以下使用的是__type_traits<T1>::is_POD_type is _POD
    typedef typename __type_traits<T1>::is_POD_type is_POD;
    return __uninitizlized_fill_n_aux(first,n,x,is_POD());
}


template<class ForwardIterator,class Size,class T>
ForwardIterator uninitialized_fill_n(ForwardIterator first,Size n,const T&x){
    return __uninitizlized_fill_n(first,n,x,value_type(first));
    //使用value_type()判断first的value type
}

参考链接

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值