STL源码剖析---根据最新版本的g++4.9.0(支持C++11)的修订(1)空间配置器

源码剖析采用的G++版本为2.91.57版本,是比较老的版本与最新版本4.9.0有某些方面的差别。现在我针对最新版本做一个分析。我下载了最新的gcc-4.9.0的包作为观察对象:

我们#include <>时的头文件放在:gcc-4.9.0/libstdc++-v3/include/std;例如vector。

真正的实现文件放在:gcc-4.9.0/libstdc++-v3/include/bits;例如:stl_vector,注意前面的stl_。

最后要说的是:技术是不断进步,不断发展变化的。两个G++版本存在差别,4.9.0版本已经很新了,但是也不能保证后来的g++版本相对现在的就不会变化,而且可以肯定的说后来的肯定会有所变化,所以我们要用发展变化的眼光看待问题,做技术的也是同样的道理。

 

1. 空间配配器allocator

allocator作为C++标准的空间配置,提供了必要的空间分配能力。

 

2. SGI真的用std::alloc

源码剖析说SGI STL用alloc作为配置器,从未使用allocator。但是在新版本中就不一样了,使用的是标准的std::allocator。

#include <iostream>
#include <memory>
#include <vector>

using std::vector;
using std::cout;
using std::endl;
using std::allocator;

int main(void)
{
    vector<int, allocator<int>> ivec;

    ivec.push_back(3);
    cout << ivec[0] << endl;

    return 0;
}

编译:

[[email protected] 桌面]# g++ allocator.cc -std=c++0x

[[email protected] 桌面]# ./a.out

3

结论:gcc 可以使用std::allocator。可以试下std::alloc发现,发现无法编译成功。

查找vector定义发现默认配置器未std::allocator:

  template<typename _Tp, typename _Alloc = std::allocator<_Tp> >

    class vector : protected _Vector_base<_Tp, _Alloc>

 

3. SGI <memory>

配置器定义于<memory>中,SGI<memory>中包含:

#include <bits/allocator.h>       //不是alloc.h,定义了内存空间的配置allocate(), 释放deallocate()

#include <bits/stl_construct.h>//负责对象昂内容的构造construct, 析构destroy()

#include <bits/stl_uninitialized.h>//定义了全局函数,用来fill或copy大块内存

 

4. c++ 提供的基本内存分配函数

4.1. 最基本的operator new, operator delete

在int *ip = new int发生了什么?

(1)调用名为opreator new的标准库函数分配足够大小的原始的未初始化的内存,以保存指定类型的对象。

(2)运行该类型的构造函数,用指定初始化式构造对象。

(3)返回指向新分配的并构造的对象的指针。

在delete ip;是发生什么?

(1)对ip指向的对象运行适当的析构函数。

(2)调用operator delete的标准库函数释放该对象所用内存。

4.2. operatro new;operator delete;

//operator new用于分配原始内存空间。

//类似C语言的malloc(size_t); C++ alloc.allocate(size_t);

void *operator new(size_t);

void *operaotr new[](size_t);

//operator delete用于回收对象所占的内存。

//类似C语言的free();C+++ alloc.deallocate();

void *operator delete(void*);

void *operator delete[](void*);

4.3. place new: 初始化原始内存空间

place new 定位new: 在已分配的原始内存空间中初始化一个对象。

new(place_address) type;

new(place_address) type(initlist-list);

相对于alloc.construct(pos, val);更灵活,可以使用任意构造函数。

而construct只能用copy constructor,对于有些类效率可能底,也有可能不支持,就只能用place new。

5. STL提供的全局的算法:#include <memory>

定义在<bits/stl_uninitialized.h>: uninitialized_copy, uninitialized_fill, uninitialized_fill_n

5.1. uninitialized_copy:POD类型调用STL算法copy(first, last, result), 非POD类型调用construct(pos, value),char*和wchar*调用memmove()。

template <class InputIterator, class ForwardIterato>

ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwareIterator result);

将内存的配置与对象的构造行为分离开来。若,[result, result + (last - first))的每一个迭代器iter都指向未初始化区域,该函数都会调用

construct(&*(result + (iter - first)), *iter),产生*iter的复制品,放置于输出范围的相对位置上。

对于容器的全区间构造函数,可以使用uninitialized_copy()在该容器的内存上构造函数。

该函数具有commit or rollback语义,要么构造出所有元素,要么(当有任何copy construct失败时),不构造任何东西。

5.2 uninitialized_fill:POD类型调用STL算法fill(first, last, x), 非POD类型调用construct(pos, value)

template <class Forwarditerator, class T>

void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T&x);

用于在未初始化的内存上构造对象, 会在[first, last)范围内产生x的复制品。即会对范围内的每个迭代器调用construct(&*i, x), 在i所指处产生x的复制品。

同样的也支持commit or rollback。

5.3. uninitialized_fill_n:POD类型调用STL算法fill_n(first, n, x), 非POD类型调用construct(pos, value)

template <class ForwardIterator, class Size, class T>

ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T &x);

与上面两个基本相同,从first开始位置,构造n个x。

 

6. allocator: 是STL提供的一个封装类,对operator new, operator delete和place new, ~T()的封装,方便分配内存。

template<typename _Tp>

    class allocator {

public:

//各种type的设计:

      typedef size_t           size_type;

      typedef ptrdiff_t        difference_type;

      typedef _Tp*            pointer;

      typedef const _Tp*   const_pointer;

      typedef _Tp&            reference;

      typedef const _Tp&   const_reference;

      typedef _Tp             value_type;

template<typename _Tp1>

        struct rebind

        { typedef allocator<_Tp1> other; };

allocator() throw() { }

allocator(const allocator& __a) throw() { }

  template<typename _Tp1>

       allocator(const allocator<_Tp1>&) throw() { }

~allocator() throw() { }

pointer

      address(reference __x) const noexcept

{ return std::__addressof(__x); }

  const_pointer

      address(const_reference __x) const noexcept

      { return std::__addressof(__x); }

  pointer

      allocate(size_type __n, const void* = 0)

      {

            if (__n > this->max_size())

            std::__throw_bad_alloc();

       return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));

      }

      void

      deallocate(pointer __p, size_type)

      { ::operator delete(__p); }

size_type

      max_size() const noexcept

{ return size_t(-1) / sizeof(_Tp); }

#if __cplusplus >= 201103L

      template<typename _Up, typename... _Args>

      void construct(_Up* __p, _Args&&... __args)

     { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

template<typename _Up>

      void 
      destroy(_Up* __p) { __p->~_Up(); }

#else

     void

      construct(pointer __p, const _Tp& __val)

      { ::new((void *)__p) _Tp(__val); }

void

      destroy(pointer __p) { __p->~_Tp(); }

#endif

    };

/// allocator<void> specialization.

template<>

  class allocator<void>

  { }

 

STL源码剖析---根据最新版本的g++4.9.0(支持C++11)的修订(1)空间配置器

时间: 2024-12-26 08:54:20

STL源码剖析---根据最新版本的g++4.9.0(支持C++11)的修订(1)空间配置器的相关文章

《STL源码剖析》---stl_iterator.h阅读笔记

STL设计的中心思想是将容器(container)和算法(algorithm)分开,迭代器是容器(container)和算法(algorithm)之间的桥梁. 迭代器可以如下定义:提供一种方法,能够依序寻访某个容器内的所有元素,而又无需暴露该容器的内部表达方式. 在阅读代码之前,要先了解一个新概念:Traits编程技法 template <class T> struct MyIter { typedef T value_type //内嵌型别声明 T *ptr; MyIter(T *p = 0

STL 源码剖析 算法 stl_algo.h -- lower_bound

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie lower_bound(应用于有序区间) -------------------------------------------------------------------------------------------------------------------------- 描述:二分查找,返回一个迭代器指向每一个"不小于 value "的元素, 或 value 应该

STL 源码剖析 算法 stl_algo.h -- upper_bound

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie upper_bound(应用于有序区间) ------------------------------------------------------------------------------------------------------------------------------------------------- 描述:受STL区间前闭后开习惯的影响,upper_boun

STL源码剖析 — 空间配置器(allocator)

前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配置器,配置的对象,是内存.(以下内容来自<STL源码剖析>) 空间配置器的标准接口 根据STL的规范,allocator的必要接口 各种typedef 1 allocator::value_type 2 allocator::pointer 3 allocator::const_pointer 4

STL&quot;源码&quot;剖析-重点知识总结

STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合套用: 容器(Containers):各种数据结构,如:vector.list.deque.set.map.用来存放数据.从实现的角度来看,STL容器是一种class template. 算法(algorithms):各种常用算法,如:sort.search.copy.erase.从实现的角度来看,STL算法

C++ 《STL源码剖析》学习-vector

本文章是笔者学习<STL源码剖析>的学习笔记,记录的是笔者的个人理解,因为个人的水平有限,难免会有理解不当的地方,而且该书出版的时间比较久,难免会有些不一样.如有不当,欢迎指出. vector是c++中经常用到的数据结构,而且在面试时也会有提及,因此了解vector很重要. 一说到vector,我们就很容易想到另外一个与它十分相似的数据结构,关于它们之间显著的差别,我觉得是在于空间运用的灵活性上.数组是静态的,在声明的时候就要指明其具体的空间大小,而vector是动态的,随着元素的增加,它内部

STL 源码剖析 算法 stl_algo.h -- equal_range

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie equal_range(应用于有序区间) -------------------------------------------------------------------------------------------------------------------------------------- 描述:利用二分查找找到一个区间,区间里的所有值都等于给定值,返回的是一个pair

《STL源码剖析》---stl_alloc.h阅读笔记

这一节是讲空间的配置与释放,但不涉及对象的构造和析构,只是讲解对象构造前空前的申请以及对象析构后空间怎么释放. SGI版本的STL对空间的的申请和释放做了如下考虑: 1.向堆申请空间 2.考虑了多线程.但是这节目的只是讲解空间配置与释放,因此忽略了多线程,集中学习空间的申请和释放. 3.内存不足时的应变措施 4.考虑到了内存碎片的问题.多次申请释放小块内存可能会造成内存碎片. 在C++中,内存的申请和释放是通过operator new函数和operator delete函数,这两个函数相当于C语

STL 源码剖析 stl_numeric.h -- copy

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie copy //唯一对外接口 /*-------------------------------------------------------------------------------------- * copy 函数及其重载形式 */ //完全泛化版本. template<class InputIterator, class OutputIterator> // ? 这里的 In