- 初始化空间的五个函数
- 构造函数 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 _PODtypedef 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 _PODtypedef 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
}
参考链接
- C++ STL __type_traits解析 - 知乎