STL—list

前面我们分析了vector,这篇介绍STL中另一个重要的容器list

list的设计

list由三部分构成:list节点、list迭代器、list本身

list节点

list是一个双向链表,所以其list节点中有前后两个指针。如下:

// list节点
template <typename T>
struct __list_node
{typedef void* void_pointer;void_pointer prev; // 指向前一个节点void_pointer next; // 指向下一个节点T data; // 节点的值
};

list迭代器

前面我们说过vector是利用其内存分配类型成员给vector分配一大块内存,而其迭代器是原始指针,所以其迭代器的移动就是指针的移动,vector那样通过指针的移动就能得到下一个元素,不需要特别设计。而list是链表结构,链表中每个节点的内存不连续,list的迭代器就是对外隐藏了从一个节点是如何移动到下一个节点的具体细节,使得外部只要将迭代器自增或自减就能得到相邻的节点。

list迭代器只有一个指向链表节点的指针数据成员。如下:

        typedef __list_node<T>* link_type;link_type node;  // point to __list_node

下面是迭代器的前置自增和前置自减运算符的源码,可以看到是通过节点的前向和后向指针来完成从一个节点移动到另一个节点:

        self& operator++() { node = (link_type)(*node).next; return *this;}self& operator--() { node = (link_type)(*node).prev; return *this;}

list

和vector一样,list也有个空间配置器的类型成员,通过该类型来为list的每个节点分配内存,并且通过该类型成员将外部指定的节点数目转换为相应节点所需的内存所以list的内存模型是每个链表节点分配一块单独的内存,然后将每个节点连接起来。而vector的内存模型是分配一大块连续的内存。如下:

          // 空间配置器typedef simple_alloc<list_node, alloc> list_node_allocator;

 

实际上,list不仅是一个双向链表,而且还是一个环状的双向链表。为了设计的方便,在list中放置一个node指针,该指针指向一个空白节点,该空白节点的下一个节点是链表中起始节点,而链表的尾节点的下一个节点为该空白节点。虽然list底层是一个环状双向链表,但通过这样设计后对外就表现出一个普通的双向链表,符合一般习惯。这样设计还有很多好处,比如快速得到链表的首尾节点。如下。

private://指向空白节点
        link_type               node;
public:// 通过空白节点node完成iterator begin() const { return (link_type)(*node).next; }iterator end() const { return node;}bool empty() const { return node->next == node; }

 

下面我们看list内部是如何构造一个链表的。以我们对list的常用使用方法 list<int> lis(10)为例:

首先调用构造函数

        explicit list(size_type n){empty_initialize();insert(begin(), n, T());}

该构造函数会先调用empty_initialize()为list分配一个空白节点,并设置前向后向指针

        void empty_initialize(){node = get_node();node->next = node;node->prev = node;}link_type get_node() { return list_node_allocator::allocate(1);}

然后构造函数会循环以插入相应个数的链表节点,每次插入时会分配一个节点大小的内存,然后对这块内存初始化,注意插入位置是在指定位置之前插入。由于list的内存模型和vector内存模型的区别,vector每次插入时由于可能会造成内存的重新配置,会造成原先所有的迭代器失效。而list的插入只是为新节点分配内存,并将其添加到链表中,对链表中其他节点的内存不会造成影响,所以list的插入则不会引起迭代器失效。如下。

template <typename T>
void
list<T>::insert(iterator position, size_type n, const T& x)
{for (; n > 0; --n)insert(position, x);
}

template
<typename T> void list<T>::insert(iterator position, const T& x)//posiiton之前插入 {link_type tmp = create_node(x);tmp->next = position.node;tmp->prev = position.node->prev;(link_type(position.node->prev))->next = tmp;position.node->prev = tmp; }
link_type create_node(
const T& x) {link_type p = get_node();construct(&p->data, x);return p; }
link_type get_node() {
return list_node_allocator::allocate(1);}

 

(全文完)

附:
STL系列文章:http://www.cnblogs.com/zxiner/p/7197402.html
一款简易版STL的实现,项目地址:https://github.com/zinx2016/MiniSTL/tree/master/MiniSTL

转载于:https://www.cnblogs.com/zxiner/p/7202558.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289090.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#语法糖 Null 条件运算符 【?.】

例子比如说:我们有一个UserInformation类public class UserInformation{ public string Name { get; set; }public List<string> Address { get; set; }}有下面一段代码,我们获取张三的第一个地址static void Main(string[] args){UserInformation user new UserInforma…

用单片机测量流体流速的_流量测量的主要方法

电磁流量计由于流量检测的复杂性和多样性&#xff0c;流量检测的方法非常多&#xff0c;常用于工业生产中的有10多种。流量测量与仪表可以分为测量瞬时流量和总流量两类。生产过程中流量大多作为监控参数&#xff0c;测量的是瞬时流量&#xff0c;但在物料平衡和能源计量的贸易…

C#帮助控件HelpProvider的使用

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace 帮助控件的使用 {public partial class Form1 : Form{public Form1(…

mysql申请审核系统_Mysql审核工具archery

Mysql审核工具archery系统&#xff1a;Centos6.8ip:192.168.122.150安装Python和virtualenv编译安装[rootwww ~]# yum install wget gcc make zlib-devel openssl openssl-devel[rootwww src]# wget "https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tar.xz"[…

iOS——Core Animation 知识摘抄(二)

阴影 主要是shadowOpacity 、shadowColor、shadowOffset和shadowRadius四个属性 shadowPath属性 我们已经知道图层阴影并不总是方的&#xff0c;而是从图层内容的形状继承而来。这看上去不错&#xff0c;但是实时计算阴影也是一个非常消耗资源的&#xff0c;尤其是图层有多个子…

Blazor University (11)组件 — 替换子组件的属性

原文链接&#xff1a;https://blazor-university.com/components/replacing-attributes-on-child-components/替换子组件的属性源代码[1]到目前为止&#xff0c;我们已经了解了如何创建代码生成的属性[2]&#xff0c;以及如何捕获意外参数[3]。除了这两种技术之外&#xff0c;B…

HTTPS实现原理

HTTPS实现原理 HTTPS&#xff08;全称&#xff1a;Hypertext Transfer Protocol over Secure Socket Layer&#xff09;&#xff0c;是以安全为目标的HTTP通道&#xff0c;简单讲是HTTP的安全版。即HTTP下加入SSL层&#xff0c;HTTPS的安全基础是SSL。其所用的端口号是443。…

Android之在ubuntu上过滤多条关键字日志

1 问题 比如我们在查问题的时候,需要过滤多个关键字,我平时的做法是一个终端执行下面的命令,然后几个关键字就几个终端,切换来切换去不方便看日志 adb logcat | grep **** 2 改进办法 今天看到同事用了grep -E,我们可以通过-E这个参数过滤多个关键字,比如 adb logcat | gre…

C#使用ServiceController控制windows服务

C#中,使用ServiceController类控制windows服务,使用之前要先添加引用:System.ServiceProcess,然后在命名空间中引用:using System.ServiceProcess。下面举例获取本机的所有已安装的Windows服务和应用,然后查找某一应用活服务是否已经安装。 代码: using System; using S…

电信aep平台是什么意思_江苏天鼎证券:股票平台跳水是什么意思?股票为什么会跳水?...

相信很多新手在刚玩股票的时候会遇到很多的专业的基础知识不能理解&#xff0c;比如什么是跳水?为什么会跳水呢?接下来就为大家详细来说股票的跳水以及为何会跳水。一、股票平台跳水是什么意思?股票跳水通常指股价在较短的时间内&#xff0c;出现从高位下降到低位的现象。出…

设计模式六大原则(5):迪米特法则

设计模式六大原则&#xff08;5&#xff09;&#xff1a;迪米特法则 定义&#xff1a;一个对象应该对其他对象保持最少的了解。 问题由来&#xff1a;类与类之间的关系越密切&#xff0c;耦合度越大&#xff0c;当一个类发生改变时&#xff0c;对另一个类的影响也越大。 解决方…

Android之非root手机run-as命令获取debug版本apk里面的数据(shared_prefs文件,lib下面的so,数据库文件)

1 问题 非root手机想要获取debug版本的apk里面的数据(shared_prefs文件,lib下面的so,数据库文件) 2 直接用run-as命令 adb shellrun-as package-name 然后就直接进入当前apk目录了,比如 如下 /data/data/packageName 我们可以看到很多文件执行命令ls -al命令,显示结果如…

mysql mgr简介_MySQL Group Replication(MGR)使用简介与注意事项

MySQL Group Replication(MGR)是MySQL官方在5.7.17版本引进的一个数据库高可用与高扩展的解决方案&#xff0c;以插件形式提供。MGR基于分布式paxos协议&#xff0c;实现组复制&#xff0c;保证数据一致性。内置故障检测和自动选主功能&#xff0c;只要不是集群中的大多数节点都…

css改变谷歌浏览器的滚动条样式

详细内容请点击 /*---滚动条默认显示样式--*/::-webkit-scrollbar-thumb{height:50px;outline-offset:-2px;outline:2px solid #fff;-webkit-border-radius:4px;border: 2px solid #fff;}/*---鼠标点击滚动条显示样式--*/::-webkit-scrollbar-thumb:hover{height:50px;-webkit-…

C#创建PDF文档

说明:本实例用到了第三方组件ICSharpCode.SharpZipLib.dll、itextsharp.dll,该组件可到网上下载。 代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text…

【矩阵乘法】OpenJ_POJ - C17F - A Simple Math Problem

算(74*sqrt(3))^n的整数部分&#xff08;mod 1e97&#xff09;。 容易想到矩乘快速幂&#xff0c;但是怎么算整数部分呢&#xff1f; (74*sqrt(3))^n一定可以写成ab*sqrt(3)&#xff0c;同理(7-4*sqrt(3))^n一定可以写成a-b*sqrt(3)&#xff0c;于是&#xff0c; (74*sqrt(3))^…

如果通过 C# 实现对象的深复制 ?

咨询区 NakedBrunch我想实现 引用类型对象 之间的深复制&#xff0c;也就是在新的对象上修改不会影响到老的对象&#xff0c;我用了 C# 提供的 Clone 方法。MyObject myObj GetMyObj(); // Create and fill a new object MyObject newObj myObj.Clone();但貌似这样行不通&…

centos安装与配置R语言

Linux下安装R语言 一、编译安装 由于采用编译安装&#xff0c;所以需要用到gcc编译环境&#xff0c;在编译前check文件时还会用到libXt-devel和readline-devel两个依赖&#xff0c;所以在编译R语言源码时先将这些工具和依赖包准备好。readline-devel 也可以不安装&#xff0c;不…

python beautifulsoup4 table tr_python BeautifulSoup解析表

牧羊人nacy这是通用的工作示例(表数据)标记。它返回带有内部列的行的列表。第一行仅接受一个(表头/数据)。def tableDataText(table): rows [] trs table.find_all(tr) headerow [td.get_text(stripTrue) for td in trs[0].find_all(th)] # header row i…

linux之让终端支持C++11/14编译cpp文件

1 问题 我们的项目很多智能指针,但是我linux的终端肯定不支持C11/14, 我们平时都是用的下面的命令编译c文件 g -g file.cpp -o file r 如果是用c11编译需要改成如下 g -g -Wall -stdc11 file.cpp -o file 如果是用C14编译需要改成如下 g -g -Wall -stdc14 file.cpp -o f…