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()。
本文探讨了C++中空间配置器在处理内存时涉及的构造、析构、uninitialized_copy、uninitialized_fill及uninitialized_fill_n等操作。这些操作在处理未初始化内存时确保了对象正确构造,并遵循全部成功或全部不成功的语义。POD类型在其中扮演重要角色,它们的构造和析构可以更高效地进行。
1161

被折叠的 条评论
为什么被折叠?



