c++之顺序容器

这篇具有很好参考价值的文章主要介绍了c++之顺序容器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

顺序容器

sequential container

  • 向容器中添加或从容器中删除元素的代价
  • 非顺序访问容器中元素的代价

string和vector中元素保存在连续的内存空间,由于元素时连续存储的,所有下表计算地址非常快,当从容器中间位置添加或删除元素非常耗时。

list和forward_list连个容器在任意位置添加和删除操作很快,但不支持随机访问。

deque与string和vector类似,支持快速随机访问。与string和vector一样,在deque的中间位置添加或删除元素代价很高。在deque的两端添加或删除元素很快。

array与内置数组相比更安全,更容易使用。它与内置数组类似,array对象大小固定,不支持添加和删除元素以及改变容器大小的操作。

forward_list没有size操作。

选择容器的原则:

  • 优先选vector。

  • 如果程序要求随机访问元素,使用vector后deque。

  • 如果程序要求在容器中间插入或删除元素,使用list或forward_list。

  • 如果程序在头尾插入或删除元素,但不在中间位置进行插入或删除,使用deque。

  • 如果程序只有读取输入时才需要在容器中间位置插入元素,随后需要随机访问元素。

    使用vector,然后重排容器元素,避免在中间位置添加元素。

    如果必须在中间位置插入元素,先用list,然后将list拷贝到vector。

顺序容器概览

迭代器

  • 如果begin与end相等,则范围为空
  • 如果begin与end不等,则范围至少包含一个元素,且biegin指向范围中的第一个元素
  • 我们可以对begin递增若干次,使得begin==end

容器类型成员

元素类型 value_type

vector<int> c{1,2,3,3,4,5,6,8};
vector<int>::value_type tt;
tt = c[0]

元素的左值类型reference

begin和end成员

当不需要写访问时,应使用cbegin和cend。

list<string> a = {"mm","ll","kk"};
list<string>::iterator it1 = a.begin(); //显式指定类型
list<string>::const_iterator it2 = a.begin();
auto it3 = a.begin();//仅当a是const时,it3是const_iterator
auto it4 = a.cbegin();//it8是const_iterator

容器定义和初始化

将一个容器初始化为另一个容器的拷贝
方法1:直接拷贝整个容器,元素类型和容器类型必须相同

list<string> a = {"mm","ll","kk"};
vector<const char*> ar = {"a","b","c"};
list<string> b(a); //正确

方法2:(array除外)拷贝由一个迭代器对指定的元素范围。不要求容器类型相同。

forward_list<string> words(ar.begin(),ar.end());

迭代器表示拷贝的第一个元素和尾元素之后的位置。

//拷贝元素,直到(但不包括)it指向的元素

deque<string> aut(aut.begin(),it);

列表初始化

显式的指定了容器中每个元素的值,隐式的指定了容器大小。

list<string> a = {"mm","ll","kk"};

与顺序容器大小相关的构造函数

另一个构造函数,接受一个容器大小和一个(可选)元素初始值。

vector<int> ivec(10,-1); //10个int元素,每个初始化为-1
deque<string> svec(10); //10个元素,每个都是空string

标准库array具有固定大小

定义array时,除了指定元素类型,还要指定容器大小:

array<int,42>  //类型为:保存42个int的数组

为了使用array类型,必须同时指定元素类型和大小:

array<int,10>::size_type i ; //数组类型包括元素类型和大小

对array初始化时,初始化的数目必须等于或小于array的大小。

array<int,10> ia1;
array<int,10> ia2 = {0,1,2,3,4,5,6,7,8,9}; 
array<int,10> ia3 = {42};//ia3[0]为42,剩余元素为0

不能对内置数组进行拷贝或对象赋值,但array并无此限制

int digs[3] = {1,2,3};
int copy[3] = digs; //错误:内置数组不支持拷贝或赋值
array<int,3> digs = {1,2,3};
array<int,3> copy = digs; //正确

赋值和swap

赋值运算符适用于所有容器。

c1 = c2; //将c1的内容替换为c2中元素的拷贝
c1 = {a,b,c} //赋值后,c1大小为3
array<int,10> a1 = {1,2,3,4,5,6,7,8};
array<int,10> a2 = {0};
a1 = a2;
a2 = {0}; //错误,不能将一个花括号列表赋予数组

使用assign(仅顺序容器)

赋值运算符要求左边和右边的运算对象具有相同的类型。它将右边运算对象中所有元素拷贝到左边运算对象中。

list<string> names;
vector<const char*> oldstyle;
names = oldstyle; //错误:容器类型不匹配
names.assign(oldstyle.begin(),oldstyle.end());

用法2:

list<string> slist1(1);
slist1.assign(10,"hiya");

使用swap

swap操作交换两个相同类型容器的内容。元素本身并未交换,swap只是交换了两个容器的内部数据结构。

vector<string> svec1(10);
vector<string> svec2(10);
swap(svec1,svec2);

除string外,指向容器的迭代器、引用和指针在swap操作之后都不会失效。

与其他容器不同,swap两个array会真正交换他们的元素。

容器大小

每个容器有3个大小相关的操作,size、empty和max_size。forward_list不支持size。

关系运算符

关系运算符左右两边的运算对象必须是相同类型的容器,且必须保存相同类型的元素。

vector<int> v1 = {1,3,5,7,9,12}
vector<int> v2 = {1,3,9}
vector<int> v3 = {1,3,5,7}
vector<int> v1 = {1,3,5,7,9,12}
v1 < v2 //true v1和v2在元素[2]处不同,v1[2]小于等于v2[2]
v1 < v3 //false 所有元素相等,v1元素多于v3
v1 == v4 //true
v1 == v3

只有当元素类型也定义比较运算符时,才能使用关系运算符。

顺序容器操作

向顺序容器添加元素

使用push_back

除array和forward_list之外,每个顺序容器(包括string类型)都支持push_back。

由于string是一个字符容器,也可以用push_back在string末尾添加字符:

void pluralize(size_t cnt,string &word)
{
    if(cnt > 1)
    	word.push_back('s'); //等价于 word += 's'
}

使用push_front
list、forwoard_list和deque容器支持push_front。

list<int> ilist;
for(size_t ix = 0; ix != 4; ++ix)
	ilist.push_front(ix);

在容器中的特定位置添加元素

insert允许我们在容器中任意位置插入0个或多个元素。vector、deque、list和string都支持insert成员。forward_list提供特殊版本的insert成员。

slist.insert(iter,"Hello!")//将hello添加到iter之前的位置。

vector不支持push_front,但可以插入到begin之前,速度很慢

vector<string> svec;
svec.insert(svec.begin(),"Hello!");
list<string> slist;
slist.insert(slist.begin(),"Hello!"); //等价于slist.push_front("Hello!")

插入范围内元素

insert除第一个参数外,接受一个元素数目和一个值。

svec.insert(svec.end(),10,"Anna"); //将10个元素插入到svec的末尾。

接受的一对迭代器或一个初始化列表。

vector<string> v = {"a","b","c","d"};
slist.insert(slist.begin(),v.end()-2,v.end());
slist.insert(slist.end(),{"e","f","g"});
slist.insert(slist.begin(),slist.begin(),slist.end());//错误,不能指向slist

使用insert的返回值

通过使用insert的返回值,可以在容器中一个特定位置反复插入元素。

list<string> lst;
auto iter = lst.begin();
while(cin >> word)
	iter = lst.insert(iter,word); //等价于push_front

使用emplace

emplace_front、emplace和emplace_back构造而不是拷贝元素。分别对应push_front、insert和push_back。

允许将元素放在容器头部、一个给定位置之前或容器尾部。

c.emplace_back("888",25,15.99);
c.push_back("999",35,25.99);//错误
c.push_back(Sales_data("000",35,43.44));

emplace_back会在容器管理的内存空间中直接创建对象,而调用push_back会创建一个局部临时对象,并将其压入容器中。

c.emplace_back(); //使用Sales_data的默认构造函数
c.empalce(iter,"99999"); //使用Sales_data(string)

传递给emplace函数的参数必须与元素类型的构造函数相匹配。文章来源地址https://www.toymoban.com/news/detail-412946.html

到了这里,关于c++之顺序容器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++ Primer (第五版)-第九章 顺序容器

    如何选择合适的容器 迭代器 容器类型成员 列表初始化 赋值和Swap 容器的大小 关系运算符 9.3.1向顺序容器添加元素 访问元素 删除元素 改变容器大小 ### 容器操作可能使迭代器失效 9.5.2、改变string其他的方法 9.5.3 string搜索操作

    2023年04月17日
    浏览(36)
  • C++标准库 -- 顺序容器 (Primer C++ 第五版 · 阅读笔记)

    所有容器类都共享公共的接口,不同容器按不同方式对其进行扩展。 这个公共接口使容器的学习更加容易—我们基于某种容器所学习的内容也都适用于其他容器。 每种容器都提供了不同的性能和功能的权衡。 下表列出了标准库中的顺序容器, 所有顺序容器都提供了 快速顺序

    2023年04月17日
    浏览(76)
  • 【torch.nn.Sequential】序列容器的介绍和使用

    nn.Sequential是一个有序的容器,该类将按照传入构造器的顺序,依次创建相应的函数,并记录在Sequential类对象的数据结构中,同时以神经网络模块为元素的有序字典也可以作为传入参数。 因此,Sequential可以看成是有多个函数运算对象,串联成的神经网络,其返回的是Module类型

    2024年02月04日
    浏览(34)
  • pytorch容器之nn.Sequential, nn.ModuleList, nn.ModuleDict介绍

      在深度学习模型创建的时候,我们经常会碰到 nn.Sequential , nn.ModuleList , nn.ModuleDict 这三个东西,尤其是在迁移学习训练的时候经常碰到,他们到底是什么,怎么用的,使用的时候有哪些注意事项,通过这篇博文浅记一下。   在介绍这三个容器之前,我们需要先知道什么

    2024年02月08日
    浏览(31)
  • 什么是容器(Container)?

    在软件开发中,容器(Container)是一个提供运行环境和资源管理的软件平台。它负责管理和组织应用程序的组件、依赖关系和资源,并提供一系列的服务和功能,使得应用程序能够在容器中运行和交互。 容器可以是各种不同的类型,比如应用服务器、Web服务器、操作系统容器

    2024年02月15日
    浏览(30)
  • PyTorch三种主流模型构建方式:nn.Sequential、nn.Module子类、nn.Module容器开发实践,以真实烟雾识别场景数据为例

    Keras和PyTorch是两个常用的深度学习框架,它们都提供了用于构建和训练神经网络的高级API。 Keras: Keras是一个高级神经网络API,可以在多个底层深度学习框架上运行,如TensorFlow和CNTK。以下是Keras的特点和优点: 优点: 简单易用:Keras具有简洁的API设计,易于上手和使用,适合

    2024年02月11日
    浏览(75)
  • 十一. Kubernetes 容器 container 设置详解

    pod是k8s的基本单位,用k8s部署的应用运行在container容器中, 容器运行在pod中,pod又运行在k8s的节点上,一个pod内部可以启动多个container容器,所以pod又称为容器组(pod内部运行的docker容器,使用docker容器启动服务时一个容器只能启动一个服务,使用k8s后,pod是k8s的基本单位一个pod中可以运

    2024年02月08日
    浏览(35)
  • Docker基本操作之删除容器Container和删除镜像IMAGE

    1.1 删除容器Container语法 1.2 删除容器Container 操作 删除容器Container使用docker rm 命令,例如删除mysql容器: 1.3 docker ps docker ps 语法: docker ps 各个参数的说明: 2.1 删除镜像IMAGE语法 删除镜像IMAGE使用 docker rmi 命令,例如删除 mysql 镜像: 2.2 docker images 各个参数的说明: 2.3 强制删

    2024年02月14日
    浏览(32)
  • vue+ElementPlus框架Container 布局容器不能铺满整个屏幕

    直接使用ElementPlus框架的Container 布局容器,在页面中没有铺满,查看可知,有padding20px,高度也只有一半,因此添加了scc。 .common-layout { height: 100vh; }

    2024年02月04日
    浏览(27)
  • Container ansible disguises local ansible 【容器 ansible 伪装本地 ansible】

    预备条件: ctr crictl $ nerdctl containerd install 了解 kubespray 是什么 kubespray 包含 ansible、ansible-playbook命令以及通过kubespray项目安装kubernetes集群的介质。 编排 inventory.ini

    2024年01月21日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包