C++ 顺序容器学习笔记(一)

容器类型与选择

所有顺序容器都提供了快速顺序访问元素的能力。但是它们的应用有各自优缺点:

  • 像容器添加或从容器中删除元素的代价
  • 像顺序访问容器中元素的代价
    在这里插入图片描述
    注:array的长度是固定的

在实际应用时选择容器的基本原则:

  • 通常,使用vector是最好的选择,除非有特殊需求
  • 如果程序中有很多小的元素,且空间的额外开销很重要,则不要使用listforward_list
  • 如果程序要求随机访问元素,应使用vectordeque
  • 如果程序要求在容器的中间插入或删除元素,应该使用listforward_list
  • 如果程序需要在头尾位置插入或删除元素,但是不会在中间位置进行插入或删除操作,则使用deque
  • 如果程序只有在读取输入时才需要在容器中间位置插入元素,随后需要随机访问元素,则:
    —— 首先,确定是否真的需要在容器中间位置添加元素。当处理输入数据时,通常可以很容易地向vector追加数据,然后再调用标准库地sort函数来重排容器中地元素,从而避免再中间位置添加元素。
    —— 如果必须在中间位置插入元素,考虑在输入阶段使用list,一旦输入完成,将list中地内容拷贝到一个vector中。

容器操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

迭代器

一个迭代器范围可以由一对迭代器表示,两个点带起分别指向同一个容器中地元素或者尾元素之后地位置。这两个迭代器通常被称为beginend

重要问题:begincbegin两个函数有什么不同?
答:beginend都有多个版本,分别返回普通、反向和const迭代器cbegin时C++新标准引入的,用来与auto结合使用。它返回指向容器第一元素的const迭代器,可以用来只读地访问容器元素,但不能对容器元素进行修改。
begin被重载过,由两个版本,其中一个是const成员函数,也返回const迭代器,另一个则返回普通迭代器,可以对容器元素进行修改。

list<string>::iterator it5 = a.begin(); // 返回普通迭代器
list<string>::const_iterator it6 = a.begin(); // 返回const迭代器
auto it7 = a.begin(); // 返回普通迭代器
autoit8 = a.cbegin(); // 返回const迭代器

当auto与begin或end结合使用时,获得地迭代器类型依赖于容器类型,与我们想要如何使用迭代器毫不相干(建议以auto来获取迭代器)

容器定义及初始化

在这里插入图片描述

基于拷贝的初始化
// 每个容器由三个元素,用给定的初始化器进行初始化
list<string> authors = {"Milton", "Shakespeare", "Austen"};
vector<const char*> articles = {"a", "an", "the"};

list<string> authors list2(authors); // True,类型匹配
deque<string> authList(authors); // False,容器的类型不匹配
vector<string> words(articles); // False,容器内元素的类型不匹配

// True, 可以转换
forward_list<string> words(articles.begin(), articles.end());
列表初始化
// 每个容器由三个元素,用给定的初始化器进行初始化
list<string> authors = {"Milton", "Shakespeare", "Austen"};
vector<const char*> articles = {"a", "an", "the"};
与顺序容器大小相关的构造函数
vector<int> ivec(10, -1) ; // 10个Int元素,每个都初始化为-1
vector<int> ivec(10); // 10个Int元素,每个都初始化为0

注:标准库的array具有固定大小,初始化长度后就不能变改

赋值和swap

赋值运算符将其左边容器中的全部元素替换为右边容器中元素的拷贝:

c1 = c2;
c1 = {a,b,c};

与内置数组不同,标准库array类型允许赋值。但是赋值号左右两边的容器类型(元素类型、长度)必须相同

array<int, 3> a1 = {1, 2, 3};
array<int, 3> a2 = {0};
a1 = a2; // True, 替换a1中的元素
a2 = {0}; // False, 左右类型不同

在这里插入图片描述

使用assign(仅顺序容器)
// 每个容器由三个元素,用给定的初始化器进行初始化
list<string> authors = {"Milton", "Shakespeare", "Austen"};
vector<const char*> articles = {"a", "an", "the"};

// True, 可以转换
authors.assign(articles.begin(), articles.end());
// 每个容器由三个元素,用给定的初始化器进行初始化
list<string> authors = {"Milton", "Shakespeare", "Austen"};
authors.assign(10, "Hiya");

assign的参数决定了容器中将由多少个元素(长度)以及它们的值都是什么

使用swap
vector<int> ivec1(10); 
vector<int> ivec2(24);
swap(svec1, svec2);

除array外,swap不对任何元素进行拷贝、删除或者插入操作,因此可以保证在常数时间内完成。
除string外,指向容器的迭代器、引用和指针在swap操作之后都不会失效。它们仍指向swap操作之前所指向的那些元素。但是,在swap之后,这些元素以及属于不同的容器了。

vector<int> ivec1(10); 
vector<int> ivec2(24);
vector<int>::iterator it = ivec1.cbegin(); // it指向ivec1的首元素
swap(svec1, svec2);
//现在it指向ivec2的首元素了

注:与其他容器不同,swap两个array会真正交换它们的元素。因此,交换两个array所需的时间与array中的元素的数目成正比
除此之外,对于array,在swap操作之后,指针、引用和迭代器所绑定的元素保持不变,但是元素值已经与另一个array中对于元素的值进行了交换

容器的关系运算符

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值