【空间配置器】内存基本处理工具

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值