C++基础回顾3——顺序容器

顺序容器概述

  • vector:可变大小数组,支持快速随机访问,在尾部之外的位置插入或删除元素可能会变得很慢。
  • deque:双端队列,支持快速访问,在头尾插入\删除速度很快
  • list:双向列表,只支持双向顺序访问,在list中任何位置进行插入\删除操作速度都很快
  • forward_list:单向链表,只支持单向顺序访问。在链表任何位置 进行插入\删除操作速度都很快
  • array:固定大小数组,支持快速随机访问,不能添加或者删除元素。
  • string:与vector相似的容器,但专门用于保存字符,随机访问快,在尾部插入\删除快。

迭代器

迭代器有公共的接口,如果一个迭代器提供某个操作,那么所有提供相同操作的迭代器对这个操作的实现方式都是相同的。例如,所有迭代器允许我们访问容器中的元素,但是通过解引用运算符实现。
一个迭代器的范围由一对迭代器表示[begin, end),这种元素范围被称为左闭合区间,其标准数学描述为自begin开始,于end之前结束。end不是指向最后一个元素,而是指向尾元素之后的位置。

  • 如果begin与end相等,则范围为空;
  • 如果begin与end不等,则范围至少包含一个元素,且begin指向该范围中的第一个元素;
  • 我们可以对begin递增若干次,使得begin==end
 while(begin != end)
 {
     *begin != end;
     begin++;
 }
list<string> a = {"Milton", "Shakespeare", "Austen"};
auto it1 = a.begin(); //list<string>::iterator
auto it2 = a.rbegin(); //list<string>::reverse_iterator
auto it3 = a.cbegin(); //list<string>::const_iterator
auto it4 = a.crbegin(); //list<string>::const_reverse_iterator

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

迭代器初始化

当将一个容器初始化为另一个容器的拷贝时,两个容器的容器类型和元素类型都必须相同。

 list<string> authors = {"Milton", "Shakespeare", "Austen"};
 vector<const char*> article = {"a", "an", "the"};

list<string> list2(authors); //正确,类型匹配
deque<string> authList(authors); //错误,容器类型不匹配
vector<string> words(articles); //错误,容器类型必须匹配

//正确:可以将const char*元素转换为string
 forward_list<string> words(article.begin(), article .end());

标准库array具有固定大小
与内置数组一样,标准库array的大小也是类型的一部分,当定义一个array时,除了指定元素类型还要指定容器大小。

 array<int , 42>;
 array<string, 10>;
int digs[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int cpy[10] = digs;  //错误:内置数组不支持拷贝或赋值
array<int, 10> digits = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
array<int, 10> copy = digits; //正确:只要数组类型匹配即合法。

赋值和swap

c1=c2 //将c1中的元素替换为c2中元素的拷贝,c1和c2必须具有相同的类型
c = {a, b, c….} //将c1中元素替换为初始化列表中元素的拷贝
swap(c1, c2) //交换c1和c2的元素。c1和c2必须具有相同的类型
c1.swap(c2) //比从c2向c1拷贝元素快得多

assign操作不适用于关联容器和array
seq.assign(i1) //将seq中的元素替换为初始化列表i1中的元素
seq.assign(n, t) //将seq中的元素替换为n个值为t的元素。

顺序容器添加元素

 c.push_back(t)
 c.emplace_back(args)

c.push_front(t)
c.emplace_front(args)

c.insert(p, t)
c.emplace(p, args)

c.insert(p, n, t)
c.insert(p, b, e)
c.insert(p, il)

向一个string,vector,或deque插入元素会使所有指向容器的迭代器、引用和指针失效。
向一个string或vector添加元素可能会引起整个对象存储空间的重新分配。重新分配一个对象的存储空间需要分配新的内存,并将元素从旧的空间移动到新的空间。
将一个对象放入一个容器中或者用一个对象来初始化容器时,实际上放入的是对象的拷贝,而不是对象本事。

emplace、emplace_front及emplace_back不是拷贝元素而是将元素放置于容器头部,emplace函数在容器中直接构造元素,传递给emplace函数的参数必须与元素类型的构造函数相匹配。

访问元素

at和下标操作只适用于string、vector、array和dequeue
back不适用于forward_list
c.back():返回c中尾元素的引用,若c为空,函数行为未定义
c.front():返回c中首元素的引用,若c为空,函数行为未定义
c[n]:返回c中下标为n的元素的引用,n是一个无符号整数。若n >= c.size(),则函数行为未定义。
c.at(n):返回c中下标为n的元素的引用,如果下标越界,则抛出out_of_range异常。

删除元素

 c.pop_back();
 c.pop_front();
 c.earse(p);
 c.clear();
 c.earse(b,e);
  • forward_list有特殊版本的earse
  • forward_list因时双向链表所以不支持pop_back
  • vector和string不支持pop_front
  • 删除dequeue中除首尾位置之外的任何元素都会使所有的迭代器、引用和指针失效
  • 指向string和vector中删除点之后的迭代器、引用和指针都会失效。
  • 对于list和forward_list指向容器其他位置的迭代器(包括尾后迭代器和首前迭代器)、引用和指针仍有效。

vector管理容量

通常情况下,为了性能考虑,vector和string的实现通常会分配比新的空间需求更大的内存空间。容器预留这些空间作为备用,可用来保存更多新的元素。这种分配策略比每次添加新元素时重新分配内存空间的策略要高效得多。

 c.shrink_to_fit()
 c.capacity()
 c.reserve(n)

shrink_to_fit只适用于vector、string、deque
capacity、reserve只适用于vector和string。

额外的string和其他方法

string(cp, n)
string(s2, pos2)
string(s2, pos2, len2)

string s("hello world");
string s2 = s.substr(0, 5);
string s3 = s.substr(6);
string s4 = s.substr(6, 11);
string s5 = s.substr(12);  //抛出一个out_of_range异常

s.insert(pos, args);
s.earse(pos, leng);
s.assign(args);
s.append(args);
s.repalce(range, args);

s.finds(args);
s.rfind(args);
s.find_first_of(args);
s.find_last_of(args);
s.find_first_not_of(args);
s.find_last_not_of(args);

to_string(val);//一组重载函数。
stoi(s, p, b);
stol(s, p, b);
stoul(s, p, b);
stoll(s, p, b);
stoull(s, p, b);

stof(s, p);
stod(s, p);
stold(s, p);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值