c++标准库之顺序容器(C++ Primer)

零、顺序容器所包含的头文件

  • //支持随机访问
    vector 和 deque
  • //不支持随机访问,是通过列表来实现的
    list 和 forward_list
  • //新增的数组类型及string
    //array是不能改变大小的,定义时应指定大小,string不是容器
    array //暂不学习,不太好用
    string
  • //适配器是对上面顺序容器的一种包装,包含
    三种类型:stack\queue\priority_queue
    两个头文件:stack 和 queue
    其中priority_queue默认通过<来比较排列优先级,或者自定义cmp函数。

一、所有容器上都支持的操作:

1、类型别名
  • iterator/const_iterator
  • size_type/difference_type
  • value_type/reference/const_reference
2、构造函数
  • 默认构造函数
  • 拷贝构造函数
  • C c(b,e); 迭代器范围来初始化( array不支持)
  • C c{…}; 列表初始化
3、赋值与swap
  • 直接赋值:c1 = c2;
  • 通过初始化列表来赋值,(array不支持)
  • swap有成员函数和友元函数两个版本;友元函数更具有通用性
4、大小
std::vector<int> c;
  • c.size();
  • c.max_size(); //类似于capacity,c可保存的最大元素数量
  • c.empty();
5、添加、删除元素(不适用于array)
emplace()函数使用了c++中不定参数函数的使用机制,insert(T(args))函数使用右值拷贝的方式来初始化,
其实在效率上跟emplace一样,而且写起来更加直观
  • c.clear();
  • insert\emplace\erase有不同参数的重载函数,不同容器的接口也不同
6、关系运算符
  • == 和!= 所有的容器都支持;
  • < 、<= 、>、 >= 无序关联容器不支持
7、获取迭代器
  • c.begin(); c.end();
  • c.cbegin(); c.cend(); //此版本更具有通用性,更安全,能用尽量用
8、反向容器的额外成员(forward_list不支持)
 reverse_iterator反向指针,而且是反向的左闭右开,即左开右闭,跟iterator差一个位置。
  • std::vector::reverse_iterator b = c.rbegin();
  • c.rend();
  • c.crbegin(); c.crend();

二、顺序容器额外支持的操作

1、定义和初始化
当一个容器初始化为另一个容器的拷贝时,两个容器的容器类型和元素类型都必须相同;
而迭代器范围初始化只要求元素类型相同。
  • C c = {…}; 列表初始化的等号形式;
  • 接受大小参数的初始化(只有顺序容器支持,关联容器不支持);
    C seq(n); // 对应类型要有默认初始化
    C seq(n, t);
2、赋值与swap
赋值运算会导致左边容器内部的迭代器、引用和指针失效;
而swap操作将容器内容交换不会导致指向容器的迭代器、引用和指针失效(array和string除外)
  • 没有额外的赋值方式和swap操作;都在前面的通用操作中
  • assign操作不适用于关联容器和array,seq.assign(arg);有如下参数形式:
    迭代器范围;
    初始化列表;
    seq.assign(n,t);//n个元素t

三、向顺序容器添加元素

这些操作会改变容器的大小;array不支持这些操作;
forward_list有自己专门版本的insert和emplace函数。
forward_list不支持push_back和emplace_back操作。
vector和string不支持front的操作。
  • 当我们用对象来初始化容器时,或将一个对象插入到容器中时,实际上放入到容器中的是对象值得一个拷贝。此处是否可以通过使用std::move()来实现右值拷贝?
1、back 和front插入,返回值是void;
emplace是通过调用元素类型的构造函数来生成元素;
push则是直接添加元素,但可以进行一步默认类型转换。
  • c.push_back(t);
  • c.emplace_back(arg);
  • c.push_front(t);
  • c.emplace_front(arg);
2、insert和emplace;在所指位置的前面插入元素,返回新添加的第一个元素的迭代器
emplace的参数形式要根据元素对象的构造函数,insert有多种不同的参数列表。
  • c.emplace(p, args); //第一个参数是插入位置的迭代器,后面时对象构造函数所需参数
  • c.insert(p,t); //在p之前插入元素t,返回指向t的指针
  • c.insert(p,n,t); //在p之前插入元素,返回void
  • c.insert(p,b,e); //在p之前插入元素,返回void
  • c.insert(p,il); //在p之前插入元素,返回void;这是初始化列表的形式

四、访问元素

此部分的函数返回元素的引用
at和下标操作为随机访问,只适用于string、vector、deque和array;
back不适用于forward_list。
  • c.back(); //返回的是尾元素的的引用,与end()不同。
  • c.front();
  • c[n];
  • c.at(n); //越界将抛出out_of_range异常,比较安全。

五、删除元素

删除元素的成员函数并不检查其参数,在删除元素之前,程序员必须保证它(们)存在。
这些操作会改变容器的大小;array不支持这些操作;
forward_list有自己专门版本的erase函数。forward_list不支持pop_back操作。
vector和string不支持pop_front的操作。
1、 删除头尾的元素,c为空,行为未定义;返回void
  • c.pop_back();
  • c.pop_front();
2、 删除指定位置的元素,返回删除元素后的元素的迭代器或尾后迭代器
  • c.erase( p );
  • c.erase(b,e);
  • c.clear();

六、特殊的forward_list操作

1、访问元素
forward_list由于指针时单向的,不宜访问给定指针之前的元素,所以大多操作在给定指针之后操作。
forward_list应该有一个头节点,不保存元素,即:before_begin()的返回值。
  • lst.before_begin();
  • lst.cbefore_begin();
2、插入元素
跟insert的区别就是插入位置在给定指针之后,返回指向最后一个插入元素的迭代器。
也就是插入进行的方向跟insert相反,第一个返回指向插入元素的指针。
  • lst.insert_after(p,t);
  • lst.insert_after(p,n,t);
  • lst.insert_after(p,b,e);
  • lst.insert_after(p, il);
  • lst.emplace_after(p,args);
3、删除元素
删除p指向的位置后面的元素;删除b指向的位置后面的元素,直到e之前。
这里(b,e)不包含b和e,与之前的前闭后开的集合形式有区别。
  • lst.erase_after§;
  • lst.erase_after(b,e);

七、容器大小的操作

1、改变容器大小的操作resize()
1. resize()不适用于array
2. 调整c的大小为n个元素。如果n<c.size();则多出来的元素被丢弃;
3. 如果必须添加元素,对新元素进行值初始化。通过元素拷贝构造函数来实现初始化;
  • c.resize(n);
  • c.resize(n,t);
2、容器大小的管理操作
1. shrink_to_fit值适合于vector、string和deque;
2. capacity和reserve只适合于vector和string。
3. reserve并不改变容器中元素的数量,它仅影响vector预先分配多大的内存空间。这一点跟resize不同。
  • c.shrink_to_fit(); //将capacity()减小为与size()相同大小。(只是请求,不一定执行)
  • c.capacity();
  • c.reserve(n);

八、额外的string操作

1、构造string的其他方法
n、len2和pos2都是无符号类型;cp是指向字符数组的指针。
  • string s(cp,n); // s是cp指向的字符数组中前n个字符的拷贝。
  • string s(s2, pos2); //s是s2从下标pos2开始的字符的拷贝。
  • string s(s2, pos2, len2); //s是s2从下标pos2开始的len2个字符的拷贝,至多拷贝s2.size()-pos2个字符。
2、修改string的操作
1. 这一部分的操作形式太多,容易搞混,不宜记住所以形式,这些操作估计是为了达到c语言char[]操作的灵活度。
2. 跟顺序容器的基本操作比,有如下不同:
(1). pos,len增加了使用下标而不是使用迭代器的位置标示方法;
(2). 增加了append和replace函数。
(3). pos标示下标时返回的是元素的引用,而不是迭代器。
2.1 函数形式
  • s.insert(pos,args); //pos可以是下标,也可以是迭代器

  • s.erase(pos,len); //pos只能是下标,如果len省略,则删除从pos开始的所有元素;

  • s.assign(args);

  • s.append(args);

  • s.replace(range, args);

2.2 参数说明
1. arg可以是一下形式之一;append和assign可以使用所有形式。
2. str不能与s相同,迭代器b和e不能指向s。
  1. str //字符串str
  2. str,pos,len //str中从pos开始最多len个字符。
  3. cp //cp指向的以空字符结尾的字符数组
  4. cp,len //cp只想的字符数组的前(最多)len个字符
  5. n,c //n个字符c
  6. b,e //迭代器b,e指定的范围
  7. 初始化列表
  • insert中 pos为下标:不支持3、6、7;

  • insert中 pos为迭代器:不支持1、2、3、4

  • replace中range为pos+len:不支持6,7;

  • replace中range为beg+end:不支持2;

3、string搜素操作
1. string搜素函数返回string::size_type值,该类型为unsigned类型;最好用unsigned类型保存返回值。
2. 搜素操作返回指定字符出现的下标,如果未找到返回npos;下标操作越界的问题要比迭代器难处理,要注意
3.1 查找s中arg第一次和最后一次出现的位置
  • s.find(args);
  • s.rfind(args);
3.2 返回args中任何一个字符(或不在args中的字符)第一个或最后一个出现的下标
  • s.find_first_of(arg);
  • s.find_last_of(arg);
  • s.find_first_not_of(arg);
  • s.find_last_not_of(arg);

arg为如下形式之一,其中pos指定是s中开始的位置,pos默认值为0;

  1. c,pos
  2. s2,pos
  3. cp,pos

pos和n没有默认值,从s中pos位置开始查找cp数组的前n个字符。pos有默认值,则无法辨别输入的参数是pos还是n

  1. cp,pos,n
4、compare函数(与c中strcmp函数类似)
4.1 s1.compare(args);参数形式更多:
  • s2
  • pos1,n1,s2
  • pos1,n1,s2,pos2,n2
  • cp
  • pos1,n1,cp
  • pos1,n1,cp,n2
5、string与数值之间的转换
5.1 数值转换为string
  • to_string(val); //实现了各种算术类型重载,浮点类型和int及更大的整型;小整型会提升到int
5.2 string转换为数值
1. 返回s的一个起始子串的数值(第一个字符必须为十进制中的数字且小于b),b为转换所用基数,默认值为10;
2. p是size_t指针,用来保存s中第一个非数值字符的下标,p默认值为0(nullptr);
3. b是指字符串中数值的基数;转换成的数字都是十进制。
  • 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);

九、容器适配器

1、所有容器适配器都支持的操作和类型(与容器比较):
  1. 没有了迭代器及引用类型;增加了container_type类型。
  2. 只支持默认初始化和拷贝初始化;不支持列表初始化,范围初始化;
  3. 不支持赋值,支持swap;支持size和empty;
2、指定适配器基于的容器
  1. 默认情况下,stack 和queue是基于deque实现的,priority_queue是基于vector实现的。
  2. 但我们可以指定container类型,如下:
    stack<string, vector> str_stk;
3、stack适配器支持的操作
可在deque、vector、list之上实现
  • s.pop(); //删除栈顶元素,但不返回该元素;
  • s.push();
  • s.emplace(item); //通过构造入栈;
  • s.top(args); //返回栈顶元素,但不出栈
4、queue和priority_queue支持的操作:
priority_queue:默认情况下,标准库在元素类型上使用<运算符来确定相对优先级。
  • q.pop(); //删除queue的首元素或priority_queue的优先级最高的元素,但不返回它;

  • q.front(); //返回首元素

  • q.back(); //只适用于queue

  • q.top(); //只适用于priority_queue,优先级最高的元素

  • q.pust(item);

  • q.emplace(arg);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值