【空间配置器】构造和析构

本文详细解析了STL容器中的空间配置器如何通过`alloc::allocate()`和`alloc::deallocate()`分离内存分配与释放,以及`construct()`和`destroy()`函数在构造和析构对象时的作用。讨论了不同版本的`destroy()`函数,重点在于如何高效处理trivial destructor的情况。
摘要由CSDN通过智能技术生成


空间配置器STL容器分配 存储数据的空间,空间不一定是内存,也可以是磁盘或其它辅助存储介质。

一般而言,我们所习惯的C++内存配置操作和释放操作是这样的:

class Foo { ... };
Foo *pf = new Foo;
delete pf;

这其中的new包含两步操作:
(1)调用::operator new配置内存;
(2)调用Foo::Foo()构造对象。

delete也包含两步操作:
(1)调用Foo::~Foo()将对象析构;
(2)调用::operator delete释放内存。
详情见C++关键字new和delete

为了精密分工,STL allocator将这两步区分开来。
alloc::allocate()负责配置内存
alloc::deallocate()负责释放内存;
::construct()负责构造对象
::destroy()负责析构对象

构造对象

template <typename T1, typename T2>
inline void construct(T1 *p, const T2 &value)
{
    new (p) T1(value);
}

construct接受一个指针p和一个初值value,该函数的用途就是将value设定到指针所指的空间上。C++placement new运算可完成这一任务。

p所指向的内存一定得是预先分配好的。construct只负责向该内存中写数据。

析构对象

版本1

template <typename T>
inline void destroy(T *pointer)
{
    pointer->~T();
}

destroy函数接受一个指针,将该指针所指的对象析构掉(调用析构函数)。

版本2

destroy的另一种重载实现如下。接受firstlast两个迭代器,准备将[first, last)范围内的所有对象都析构掉。我们不知道这个范围有多大,万一很大,而且每个对象的析构函数都无关痛痒(即所谓的trivial destructor),那么一次次地调用这些析构函数只会白白地浪费CPU资源。

template <typename ForwardIterator>
inline void destroy(ForwardIterator first, ForwardIterator last)
{
    __destroy(first, last, value_type(first));
}

个人理解:所谓trivial destructor,即析构函数里没有任何自定义的行为(如将new的堆内存delete掉)。

因此,使用value_type()获得迭代器所指对象的型别,再利用__type_traits<T>判断该型别的析构函数是否是trivial的。

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) {}

不调用trivial destructor

否则循环遍历整个范围,每遍历到一个对象就调用一次destroy()

template <typename ForwardIterator, typename T>
inline void __destroy_aux(ForwardIterator first, ForwardIterator last, __false_type)
{
    while (first != last) {
        destroy(first.get());
        ++first;
    }
}

需要调用析构函数

那如何判断迭代器所指对象的型别value_type())以及析构函数是否是trivial的__type_traits<>)?

讲迭代器的时候再说。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值