STL
定义了五个全局函数,作用于
未初始化的内存上。它们分别是
construct()
、
destroy()
、
uninitialized_copy()
、
uninitialized_fill()
和
uninitialized_fill_n()
。
用于构造对象的construct()
和析构对象的destroy()
在【空间配置器】构造和析构里已有分析。
construct
template <typename T1, typename T2>
inline void construct(T1 *p, const T2 &value)
{
new (p) T1(value);
}
destroy
template <typename T>
inline void destroy(T *pointer)
{
pointer->~T();
}
template <typename ForwardIterator>
inline void destroy(ForwardIterator first, ForwardIterator last)
{
__destroy(first, last, value_type(first));
}
template <typename ForwardIterator, typename T>
inline void __destroy(ForwardIterator first, ForwardIterator last, T*)
{
typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;
__destroy_aux(first, last, trivial_destructor());
}
template <typename ForwardIterator, typename T>
inline void __destroy_aux(ForwardIterator first, ForwardIterator last, __true_type) {}
template <typename ForwardIterator, typename T>
inline void __destroy_aux(ForwardIterator first, ForwardIterator last, __false_type)
{
while (first != last) {
destroy(first.get());
++first;
}
}
uninitialized_copy
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result);
如果作为输出目的地的[result, result + (last - first)]
范围内的每一个迭代器都指向未初始化区域,则uninitialized_copy()
会使用copy constructor
构造对象。针对输入范围内的每一个迭代器i
,该函数会调用construct(&*(result + (i - first)), *i)
。
容器的全区间构造函数(如执行std::vector<int> vi = {1, 2, 3};
的时候)通常以两个步骤完成:
(1)
配置内存块,足以包含范围内的所有元素。
(2)
使用uninitialized_copy()
,在该内存上构造元素。
C++
标准规格书要求uninitialized_copy()
具有commit or rollback
语意,即要么构造出所有的元素,要么不构造任何元素。
uninitialized_fill
template <class ForwardIterator, class T>
void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T &x);
如果[first, last)
范围内的每个迭代器都指向未初始化的内存,那么uninitialized_fill()
会针对操作范围内的每个迭代器i
,调用construct(&*i, x)
在i
所指的地方生成一个x
的复制品。
和
uninitialized_copy()
一样,uninitialized_fill()
要么产生出所有必要的元素,要么不产生任何元素。如果有任何一次construct()
丢出异常,所有已经生成的元素都会被析构掉。
uninitialized_fill_n
template <class ForwardIterator, class Size, class T>
ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T &x);
如果[first, first + n)
范围内的每一个迭代器都指向未初始化区域,那对于范围内的每个迭代器i
会调用construct(&*i, x)
在对应位置处产生x
的复制品。
uninitialized_fil_n()
也具有commit or rollback
语意。
POD类型
POD
意指Plain Old Data
,也就是标量型别(scalar types
)或传统的C struct
型别,POD
必然拥有trivial
的构造、析构、拷贝构造和赋值函数。因此,要生成POD
类型的对象,可以采用更有效率的方式。
大概可以通过如下方式确定first
指向的是不是POD
类型的对象:
InputIterator first;
T *p = value_type(first); // 获取迭代器封装的指针的类型
typedef typename __type_traits<T>::is_POD_type is_POD; // 通过指针的类型确定对象是不是POD的
if (is_POD() == __true_type) { ... } // POD类型
if (is_POD() == __false_type) { ... } // 非POD类型
执行uninitialized_fill_n()
的时候,生成POD对象使用fill_n()
,生成非POD对象使用construct()
。
执行uninitialized_copy()
的时候,生成POD对象使用copy()
,生成非POD对象使用construct()
。特别地,针对char*
和wchar_t*
,使用memmove()
。
执行uninitialized_fill()
的时候,生成POD对象使用fill()
,生成非POD对象使用construct()
。