SGISTL源码探究-deque容器(上)

【实战指南】DBeaver EE Windows版高效破解与配置全解析 本文详细解析了DBeaver EE Windows版的高效破解与配置方法,涵盖Java环境配置、破解包部署、配置文件修改等关键步骤,并提供了性能优化和数据库连接的最佳实践。适用于需要解锁企业版高级功能的数据库开发人员,帮助提升工作效率。 阅读详情

前言

deque容器比list以及vector容器都要复杂的多。它用两端都有开口的线性空间来存储数据,这样的话在首部操作数据的效率比vector高,以及虽然它的迭代器是random_access_iterator_tag型的,但是并不是原生指针,需要封装,比list和vector的迭代器都要复杂。它实现的机制是利用二级指针,维护一个指针数组map,然后数组中存储的指针指向具体的线性空间。
map并不是从开头依次使用,而是先选择二级指针数组中间的部分使用,这是为了deque能够前后都加入等量的元素。我们把二级指针数组称为deque的中控器,通过中控器得到真正存储元素的空间。

deque的中控器

首先我们先简单介绍一下map相关的知识,即定义部分,这样有利于我们后面对迭代器等知识的分析。
这里先列出部分源码:

//可以看到多了一个缺省参数BufSiz=0
//具体有什么作用,我们看到后面再说
template <class T, class Alloc = alloc, size_t BufSiz = 0>
class deque {
public:                         // Basic types
  //一些常用类型的声明
  typedef T value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type& reference;
  typedef const value_type& const_reference;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;

public:                         // Iterators
  //迭代器的声明
#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
  typedef __deque_iterator<T, T&, T*, BufSiz>              iterator;
  typedef __deque_iterator<T, const T&, const T&, BufSiz>  const_iterator;
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
  typedef __deque_iterator<T, T&, T*>                      iterator;
  typedef __deque_iterator<T, const T&, const T*>          const_iterator;
#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
...
protected:                      // Internal typedefs
  /* map_pointer的类型即T **
   * 它先指向指针数组,指针数组里面的指针再指向存储元素的线性空间(即结点)
   */
  typedef pointer* map_pointer;
  /* 这里需要注意一下
   * deque容器有两个空间配置器
   * 一个用于配置元素
   * 另一个用于配置指针数组
   */
  typedef simple_alloc<value_type, Alloc> data_allocator;
  typedef simple_alloc<pointer, Alloc> map_allocator;

使用这样的设计需要注意到几个问题。虽然每一个指针指向的空间是连续的,但是当一段数据横跨多个指针指向的连续空间时,就需要指针的切换了。如果要维持这种连续空间的假象,则需要考虑到每个线性空间跳到下一个线性空间的边界情况。
以及当指针数组不够大时需要再继续分配的情况。
为了支持这些操作,deque的迭代器确实要复杂一些。下面我们就来看看deque的迭代器源码。

deque的迭代器

大概有100多行的样子,deque的迭代器除了要取元素的值这些操作以外,还需要知道指针指向的一段线性空间的首尾,不然++或者--操作的时候,无法跳转到另外一段线性空间。

template <class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {
  //声明迭代器
  typedef __deque_iterator<T, T&, T*, BufSiz>             iterator;
  typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
  static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); }
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
template <class T, class Ref, class Ptr>
struct __deque_iterator {
  typedef __deque_iterator<T, T&, T*>             iterator;
  typedef __deque_iterator<T, const T&, const T*> const_iterator;
  static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }
#endif
  //声明的5个相应型别及size_type
  typedef random_access_iterator_tag iterator_category;
  typedef T value_type;
  typedef Ptr pointer;
  typedef Ref reference;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
  //map_pointer指针
  typedef T** map_pointer;  
  typedef __deque_iterator self;

  /* 三个内部指针
   * cur指向当前元素
   * first指向当前元素所在的线性空间的首部
   * last指向当前元素所在的线性空间的尾部
   */
  T* cur;
  T* first;
  T* last;
  /* 二级指针,指向指针数组 */
  map_pointer node;
  //迭代器的构造函数
  __deque_iterator(T* x, map_pointer y)
    : cur(x), first(*y), last(*y + buffer_size()), node(y) {}
  __deque_iterator() : cur(0), first(0), last(0), node(0) {}
  __deque_iterator(const iterator& x)
    : cur(x.cur), first(x.first), last(x.last), node(x.node) {}

  /* 重载操作符*和->
   * 返回cur指向的元素的值以及地址
   */
  reference operator*() const { return *cur; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
  /* 重载操作符-
   * 计算两个迭代器指向的元素之间的个数
   * (node - x.node - 1)计算的是两个迭代器所在的线性空间中间跨过的完整的线性空间个数
   */
  difference_type operator-(const self& x) const {
    return difference_type(buffer_size()) * (node - x.node - 1) +
      (cur - first) + (x.last - x.cur);
  }

  /* 重载操作符++(前)
   * 这里可能涉及到跳到下一段线性空间的情况
   * 先将cur指向下一个元素,cur如果等于last了,证明该段空间已经没有空间可以容纳下一个元素了
   * 将node指向指针数组的下一个元素,即指向下一段线性空间,再将cur指向下段线性空间的首个元素
   */
  self& operator++() {
    ++cur;
    if (cur == last) {
      set_node(node + 1);
      cur = first;
    }
    return *this;
  }
  /* 重载操作符++(后) */
  self operator++(int)  {
    self tmp = *this;
    ++*this;
    return tmp;
  }
  /* 操作符--和++类似 */
  self& operator--() {
    if (cur == first) {
      set_node(node - 1);
      cur = last;
    }
    --cur;
    return *this;
  }
  self operator--(int) {
    self tmp = *this;
    --*this;
    return tmp;
  }
  /* 重载操作符+=
   * 这里同样也涉及到可能当前线性空间容量不够
   * 需要存储到下一段线性空间的情况
   * 就不一一赘述了
   */
  self& operator+=(difference_type n) {
    difference_type offset = n + (cur - first);
    if (offset >= 0 && offset < difference_type(buffer_size()))
      cur += n;
    else {
      difference_type node_offset =
        offset > 0 ? offset / difference_type(buffer_size())
                   : -difference_type((-offset - 1) / buffer_size()) - 1;
      set_node(node + node_offset);
      cur = first + (offset - node_offset * difference_type(buffer_size()));
    }
    return *this;
  }
  ......
  reference operator[](difference_type n) const { return *(*this + n); }

  bool operator==(const self& x) const { return cur == x.cur; }
  bool operator!=(const self& x) const { return !(*this == x); }
  /* 比较两个迭代器的大小
   * 首先判断两者是否处于同一段连续空间
   * 若处于,则比较元素大小
   * 若不处于,则比较node的大小
   * 所以并不是只是单纯的比较元素的大小,这点需要特别注意
   */
  bool operator<(const self& x) const {
    return (node == x.node) ? (cur < x.cur) : (node < x.node);
  }
  /* 该函数用于设置node指向的线性空间
   * 需要更新first和last指针
   * 而cur指针由调用set_node的函数进行合适的修改
   */
  void set_node(map_pointer new_node) {
    node = new_node;
    first = *new_node;
    last = first + difference_type(buffer_size());
  }
};

以上便是deque的迭代器部分,它的封装应该充分体现了STL中迭代器部分的精髓,屏蔽了内部的细节,将原本并不连续的空间,通过定义自己内部的指针以及重载大量的操作符,营造出迭代器的操作就跟指针一样的假象,可以使用++,比大小等操作。

deque内部常用的定义及声明

protected:                      // Data members
  /* deque容器内部定义了两个迭代器指针
   * start指向指针数组中正在使用的第一个结点
   * finish指向指针数组中正在使用的最后一个结点
   */
  iterator start;
  iterator finish;
  /* map即之前所说的指针数组
   * 而指针数组中的每一个指针又指向一段连续的线性空间(简称为结点)
   * map_size代表map中有多少个成员(指针)
  map_pointer map;
  size_type map_size;

public:                         // Basic accessors
  iterator begin() { return start; }
  iterator end() { return finish; }
  const_iterator begin() const { return start; }
  const_iterator end() const { return finish; }

  reference operator[](size_type n) { return start[difference_type(n)]; }
  const_reference operator[](size_type n) const {
    return start[difference_type(n)];
  }

  reference front() { return *start; }
  reference back() {
    iterator tmp = finish;
    --tmp;
    return *tmp;
  }
  const_reference front() const { return *start; }
  const_reference back() const {
    const_iterator tmp = finish;
    --tmp;
    return *tmp;
  }

  size_type size() const { return finish - start;; }
  size_type max_size() const { return size_type(-1); }
  bool empty() const { return finish == start; }

以上便是一些基础的函数以及内部变量,这些都很简单,只用简单的看一下就行了。唯一需要关注的就是deque内部使用了两个迭代器分别指向指针数组中指向开始的那段线性空间和结束的那段线性空间。

deque的内存申请及构造

deque容器的构造函数同样也有多个版本,接下来我们来依次分析它们,通过这些构造函数以及析构函数,也可以了解到deque关于内存的申请及释放。create_map_and_nodes函数用于申请指针数组的空间以及用于存储元素的线性空间,这个我们放在构造函数之后讲,先知道它是干什么的。

默认构造函数
/* 指针数组不申请空间
 * 并且first和finish迭代器也调用默认构造函数
 */
deque()
  : start(), finish(), map(0), map_size(0)
{
  create_map_and_nodes(0);
}
拷贝构造函数
/* 分配了空间之后
 * 讲x上面的元素拷贝过去就行了
 */
deque(const deque& x)
  : start(), finish(), map(0), map_size(0)
{
  create_map_and_nodes(x.size());
  __STL_TRY {
    uninitialized_copy(x.begin(), x.end(), start);
  }
  __STL_UNWIND(destroy_map_and_nodes());
}
初始化n个值为value的元素
deque(size_type n, const value_type& value)
  : start(), finish(), map(0), map_size(0)
{
  fill_initialize(n, value);
}
deque(int n, const value_type& value)
  : start(), finish(), map(0), map_size(0)
{
  fill_initialize(n, value);
}

deque(long n, const value_type& value)
  : start(), finish(), map(0), map_size(0)
{
  fill_initialize(n, value);
}
初始化n个值为默认值的元素
explicit deque(size_type n)
  : start(), finish(), map(0), map_size(0)
{
  fill_initialize(n, value_type());
}
迭代器范围构造
template <class InputIterator>
deque(InputIterator first, InputIterator last)
  : start(), finish(), map(0), map_size(0)
{
  //range_initialize根据迭代器的类型选择最优的初始化方式
  range_initialize(first, last, iterator_category(first));
}
create_map_and_nodes

该函数的作用如前所述,申请指针数组map的大小及线性空间。

template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::create_map_and_nodes(size_type num_elements) {
  /* 计算结点个数
   * buffer_size()返回每段线性空间能容量元素的个数
   * num_elements代表需要申请的元素的个数
   * num_nodes代表需要申请的结点个数
   */
  size_type num_nodes = num_elements / buffer_size() + 1;
  /* map至少有8个结点,最多num_nodes + 2
   * 之所以要设计成num_nodes + 2
   * 是为了当插入元素分别到尾部和首部时有一定的扩展性,而不用一插入元素就分配空间
   */
  map_size = max(initial_map_size(), num_nodes + 2);
  //使用专门申请指针数组空间的空间配置器申请
  map = map_allocator::allocate(map_size);
  /* 将nstart和nfinish指向范围内的那一段结点尽量放在申请的总结点的中央
   * 这样做是为了让首部和头部具有一样的可以容纳新元素的空间
   */
  map_pointer nstart = map + (map_size - num_nodes) / 2;
  map_pointer nfinish = nstart + num_nodes - 1;

  map_pointer cur;
  __STL_TRY {
    /* 申请一整段线性空间
     * allocate_node的原型如下
     * return data_allocator::allocate(buffer_size();
     */
    for (cur = nstart; cur <= nfinish; ++cur)
      *cur = allocate_node();
  }
#     ifdef  __STL_USE_EXCEPTIONS
  catch(...) {
    for (map_pointer n = nstart; n < cur; ++n)
      deallocate_node(*n);
    map_allocator::deallocate(map, map_size);
    throw;
  }
#     endif /* __STL_USE_EXCEPTIONS */
  //更新start和finish迭代器
  start.set_node(nstart);
  finish.set_node(nfinish);
  start.cur = start.first;
  finish.cur = finish.first + num_elements % buffer_size();
}
initialize函数

关于初始化元素的值,deque提供了两种函数。一种是fill_initialize,另一种是range_initialize。

fill_initialize
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::fill_initialize(size_type n,
                                               const value_type& value) {
  //首先先申请空间
  create_map_and_nodes(n);
  map_pointer cur;
  __STL_TRY {
    //对每个结点依次初始化
    for (cur = start.node; cur < finish.node; ++cur)
      uninitialized_fill(*cur, *cur + buffer_size(), value);
    /* 最后一个结点需要单独处理
     * 因为可能并不会填满最后的整个线性空间
     */
    uninitialized_fill(finish.first, finish.cur, value);
  }
#       ifdef __STL_USE_EXCEPTIONS
  catch(...) {
    //发生异常了,则销毁所有申请的空间
    for (map_pointer n = start.node; n < cur; ++n)
      destroy(*n, *n + buffer_size());
    destroy_map_and_nodes();
    throw;
  }
#       endif /* __STL_USE_EXCEPTIONS */
}
range_initialize

根据迭代器类型的不同,有两个版本。你可能会想,deque容器的迭代器不就是random_access_iterator_tag类型的吗,为什么这里还要区分。
这是因为范围构造的时候,可能这个迭代器是vector的迭代器或者其他容器的迭代器,first和last迭代器并不是一定就是deque容器的迭代器。

template <class T, class Alloc, size_t BufSize>
template <class InputIterator>
void deque<T, Alloc, BufSize>::range_initialize(InputIterator first,
                                                InputIterator last,
                                                input_iterator_tag) {
  create_map_and_nodes(0);
  //一个一个的插入
  for ( ; first != last; ++first)
    push_back(*first);
}

template <class T, class Alloc, size_t BufSize>
template <class ForwardIterator>
void deque<T, Alloc, BufSize>::range_initialize(ForwardIterator first,
                                                ForwardIterator last,
                                                forward_iterator_tag) {
  size_type n = 0;
  //计算出[first, last)范围内的元素个数
  distance(first, last, n);
  //申请空间
  create_map_and_nodes(n);
  //进行拷贝,若失败,销毁空间
  __STL_TRY {
    uninitialized_copy(first, last, start);
  }
  __STL_UNWIND(destroy_map_and_nodes());
}

deque的内存释放及析构

最后让我们再来看看一下deque容器是如何释放内存以及析构函数的真面目。
前面异常处理的时候,基本都调用了destroy_map_and_nodes函数。它的作用就时释放deque容器的空间。

内存释放

源码如下:

template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::destroy_map_and_nodes() {
  //依次遍历每个结点,调用deallocate_node释放空间(这里是释放的指针数组中指针指向的线性空间)
  for (map_pointer cur = start.node; cur <= finish.node; ++cur)
    deallocate_node(*cur);
  //释放指针数组
  map_allocator::deallocate(map, map_size);
}

deallocate_node函数很简单,源码就一行data_allocator::deallocate(n, buffer_size()),调用了空间配置器里面的释放空间的函数。

析构函数
~deque() {
  destroy(start, finish);
  destroy_map_and_nodes();
}

小结

在本小节我们主要介绍了deque容器的迭代器以及它使用的数据结构以及机制,还有关于内存的申请及构造函数以及内存的释放及析构函数。
重点是要理解deque容器存储元素的机制,即使用指针数组,而每个指针指向的才是真正存储元素的线性空间。还有关于deque的迭代器部分,也是比较关键的地方。在下一小节中,我们将调几个deque容器比较常用的操作来分析,因为deque的操作确实比较多….

制作3D地形图的方法-使用GlobalMapper和3ds Max软件 打开GlobalMapper软件,在菜单栏中选择“文件”>“打开数据文件”,然后选择相应的高程数据文件。在菜单栏中选择“渲染”>“渲染设置”,根据需要进行设置,如分辨率和输出格式。选择地形对象,点击菜单栏中的“渲染”>“材质编辑器”,然后根据需要调整材质属性,如颜色、纹理和光照等。在菜单栏中选择“工具”>“高程栅格和网格”>“创建地形网格”。在菜单栏中选择“文件”>“导出”>“导出栅格格式”。打开3ds Max软件,在菜单栏中选择“文件”>“导入”,然后选择之前导出的地形数据文件。步骤3:导出地形网格。 阅读详情

相关推荐

实战分享:如何利用svchost进程绕过360防护(附完整Shellcode注入教程)

本文深入解析系统进程安全防护机制,探讨svchost等关键进程的安全特性与防护策略。详细分析安全软件的行为检测和内存保护技术,提供系统加固与监控实践建议,助力企业构建多层次防御体系,有效应对潜在安全威胁。

weixin_30752699的博客 99

基于C++11的Deque容器分析

关于C++11标准下Deque容器的分析

Reol99999的博客 572

基于eBPF的零侵入LLM智能体观测:AgentSight架构与实战

在分布式系统和云原生架构中,可观测性是保障应用稳定运行与高效排障的核心能力。其原理在于通过日志、指标和追踪三大支柱,从外部视角持续收集和分析系统状态,而非依赖应用内部埋点。这一技术价值在于能以统一、低开销的方式,理解复杂系统的内部行为,尤其在微服务、容器化及Serverless等动态环境中至关重要。应用场景广泛覆盖了性能监控、安全审计、故障诊断与根因分析。当我们将这一基础理念应用于当下快速发展的AI智能体领域时,便自然引出了对LLM智能体进行无侵入、系统级行为观测的需求。传统的应用层方案需要集成SDK,对闭

weixin_28696185的博客 324

C++ STL总结(三)deque

1.deque内存结构 deque是双向开口的,即在头尾插入和删除元素效率都很高,逻辑上deque的内存结构是这样的 实际上,deque是用一个中控器map来管理这些连续的内存空间。map是一小块连续的空间,每个元素都是一个指针,指向连续的内存空间,指向的空间中存储的才是真正的deque的元素。 2.deque容量操作 函数 功能 bool empty() 检查容器是否为空 size_t size() 返回容器中元素的个数 size_t max_size() 返回容器由于系统或库

qq_36383272的博客 553

DDR的Controller、Channel、Chip、Rank、Bank、Row、Column、Sided、Dimm

DDR的Controller、Channel、Chip、Bank、Rank、Row、Column、Sided、Dimm

张飞online博客 2万+

中兴交换机配置SSH登录

SSH是在传统的Telnet协议基础上发展起来的一种安全的远程登录协议。发送和接收数据时, SSH会自动对数据进行加密及解密。相比于Telnet,SSH能防止“中间人”攻击、DNS欺骗、IP 欺骗等,无论是在认证方式或者数据传输的安全性上都有很大的提高。SSH用户认证方式有3种,分别为本地(Local)认证、RADIUS认证和TACACS+认证。以表规划数据为例,说明配置SSH登录的步骤。

才怪的博客 7922

C++/C++11中std::deque的使用

C++/C++11中std::deque的使用

网络资源是无限的 4万+

深入CARLA地图底层:OpenDRIVE文件如何影响你的仿真效果与避坑指南

本文深入解析CARLA仿真中OpenDRIVE地图文件的核心作用,揭示其如何影响车道连接、交通规则和导航逻辑。通过实战案例和代码示例,提供五大典型地图问题的诊断与修复方案,帮助开发者优化仿真效果并规避常见陷阱。

weixin_34180452的博客 277

STL之deque简要实现

(1)内存模型及实现接口 (2)源代码及简要注释 push_back、pop_back、push_front、pop_front性能和原版deque相当,insert性能慢1倍 #ifndef TINY_DEQUE #include <memory> #include <cmath> #include <cstring> name...

Keep trying until you get it right 627

Unity3D实战:5分钟搞定RTSP监控视频播放(附完整代码)

本文提供了一套在Unity3D中快速集成RTSP监控视频播放的实战方案。通过采用LibVLCSharp for Unity这一成熟稳定的跨平台中间件,开发者可以轻松实现RTSP流的解码与渲染,并附有完整的C#代码示例,帮助用户在5分钟内完成集成,适用于智慧园区、安防监控等3D可视化场景。

weixin_29001655的博客 191

Crossbar RRAM技术解析:从1TnR架构到存储革命

非易失性存储器(NVM)是数据存储的核心技术,其原理基于物理状态的稳定改变以实现数据持久化。阻变存储器(RRAM)作为一种新兴NVM,利用导电细丝在介质层中的形成与断裂实现数据存储,具有高速、低功耗和结构简单的优势。在工程实践中,RRAM面临潜行路径电流等挑战,而Crossbar提出的1TnR架构通过引入共享晶体管有效解决了这一问题,在保证性能的同时提升了集成密度。该技术与CMOS工艺兼容,支持后端集成与多层堆叠,为高密度存储和嵌入式应用提供了新的解决方案。结合当前行业对高能效、高密度存储的需求,RRAM在

weixin_42523104的博客 320

SGISTL源码探究-deque容器(下)

前言在上一小节中我们介绍了deque容器实现的大致思路以及它内部使用的一些机制,比如存储元素的空间其实是由指针数组里面的指针指向的等。 在本小节中,我们主要介绍一些deque容器封装的一些常用的操作,比如push_back、push_front、insert、erase、clear等。这些函数无非就是根据迭代器内部的first、last、cur的位置来决定进行操作。 所以有必要再重温一下firs

Move_now的博客 585

秋招突击——笔试整理——8/25——拼多多笔试整理

继续加油! 转变思维,有简单到复杂,由直观到抽象,这种贪心模拟的题目一直是这样的!

Blackoutdragon的博客 2400

SGISTL源码阅读十五 deque容器中

SGISTL源码阅读十五 deque容器中 前言 我们已经学习了deque的数据结构和它的迭代器,接下来我们继续学习它的构造及内存申请等内容。 深入源码 deque的构造函数 默认构造函数 /* 指针数组不申请空间 * 并且first和finish迭代器也调用默认构造函数 */ public: deque() : start(), finish(), map(0), map_...

Lyn&Xx 264

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

SGISTL源码阅读十六 deque容器下

SGISTL源码阅读十六 deque容器下 前言 通过之前的学习我们对deque已经有了一个比较深入的了解,如图所示: 接下来将继续学习deque的相关操作 深入源码 插入操作 向deque末尾插入一个元素 void push_back(const value_type&amp; t) { //如果deque还有足够的容量 if (finish.cur != finish.last - ...

Lyn&Xx 246

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

SGISTL源码阅读十四 deque容器上

SGISTL源码阅读十四 deque容器上 deque概述 之前我们学习过vector,我们知道他的扩容方式是从尾部扩容,也就是它是单向开口的。deque比vector和list都要更复杂一些,它是双向开口的,也就是说可以在头部和尾部做同样的操作(我们要向vector的头部添加一个元素代价是相当大的,需要将所有元素向后移动,但是对于deque来说,在头部和尾部操作都是同样的时间复杂度)。这样看起来...

Lyn&Xx 278

SGISTL源码-容器 笔记

本文是在阅读SGI STL v3.3源码中,遇到的一些问题及有意思的点。本文建立在已经观看过侯捷老师STL源码剖析课程的基础上。是在阅读源码过程中,对其中的内容进行补充、修饰。

weixin_46065476的博客 596

SGISTL源码探究-stack配接器

前言迄今为止,我们已经分析了vector、list、deque容器,而stack并不是一个容器,它是依据一种容器作为底层结构,然后根据自己的要求改变容器提供的接口。而在SGISTL的实现中,stack默认是以deque为底部结构,并且封装了一些接口并且stack中没有迭代器,它也并不需要,因为栈这种结构,并不支持遍历等操作,而出栈入栈这些操作,直接使用deque提供的操作,然后自己封装一下就行了。

Move_now的博客 728

SGISTL源码阅读十七 stack(栈)

SGISTL源码阅读十七 stack(栈) 前言 前面我们已经学习了序列式容器vector,list和deque。 本次要进行分析的是stack,它是一种先进后出(First In Lat Out,FILO)数据结构,在学习数据结构的时候应该都接触过,在这里stack是一个配接器(adapter),它默认以deque容器作为它的底部结构实现。接下来我们深入源码进行学习。 配接器 具有这种“修改某...

Lyn&Xx 444

SGISTL源码探究-queue配接器

前言在本小节中,我们将分析queue,即队列,这种数据结构的元素符合先进先出(FIFO)的条件。它同stack一样,不算是一种容器,而是采用一种容器(SGISTL中默认是deque)作为底层结构并修改部分接口为自己所用的配接器。queue同stack一样,不支持元素的遍历操作,因此并不需要迭代器。它的所有接口都依靠底层的容器实现。queue源码定义部分#ifndef __STL_LIMITED_DE

Move_now的博客 770

SGISTL源码阅读十九 set关联式容器

SGISTL源码阅读十九 set容器 前言 之前我们已经分析了vector,list,deque三个容器。如果按照“数据在容器中的排列”特性,容器可以分为序列式(sequence)和关联式(associative)两种,前面学习过的三种容器都是序列式容器。 接下来我们将学习关联式容器。标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体muiltiset(多键集合...

Lyn&Xx 321

SGISTL源码阅读十八 queue(队列)

SGISTL源码阅读十八 queue(队列) 前言 和上一篇文章提到过的stack一样,queue也是一种配接器(adapter),它们的实现非常类似。 它是一种(First In First Out,FIFO)的数据结构,也没有提供遍历或指定位置访问等操作,只能从末端添加元素,顶部取出元素,所以它也没有迭代器。 深入源码 queue的定义部分 #ifndef __STL_LIMITED_DEFA...

Lyn&Xx 313

SGISTL源码探究-配接器

前言关于配接器,之前在分析序列式容器时就已经分析过queue和stack,它们也是配接器的一种,通过使用其他容器的接口然后自己加以修饰,形成另外一种容器。除了应用在容器上之外,还有关于应用在仿函数上的配接器,就如我们上一小节分析仿函数时里面的例子一样。还有一种是应用在迭代器上的配接器,等下我们会进行分析。应用于容器的配接器关于这一部分,之前已经分析过queue和stack的实现了,这里就不做赘述了。

Move_now的博客 447

带你深入理解STL中的deque,并封装stack和queue

deque 是 double-ended queue 的缩写,又称双端队列容器。deque和vector的最大差异,一在于deque允许于常数时间内对头端进行元素的插入或移除操作,二在于deque没有所谓的容量(capacity) 观念,因为它是以动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。也因此,deque没有必要提供所谓的空间保留功能(reserve)功能。当需要向序列两端频繁的添加或删除元素时,应首选 deque 容器。

m0_61227789的博客 389

C++容器总结(一)

在模板类的定义中,template 的T表示占符位,本身没有实际意义,用T或者Type都可以。这里的T表代表了一个不确定的数据类型,可以为任意的数据类型,可以是int、double、char等,而具体是那个类型则是创建对象的时候指定。这样就可以达到模板类处理任何数据类型的目的,提高代码的复用率。在每一个成员函数的定义都包含“template ”和“MyTemplate”,表明这是一个模板类MyTemplate的成员函数。

jieer___的博客 467

栈与队列介绍

栈和队列的一些补充

wtlll的博客 300

[C++]---STL中的栈与队列进一步理解(stl中的底层实现

STL中的栈与队列进一步理解(stl中的底层实现

zjjaibc的博客 504
上一篇: SGISTL源码探究-list容器(下)
下一篇: SGISTL源码探究-deque容器(下)
UKey_
博客等级 码龄10年 258粉丝 186原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值