c++ primer/第九章 顺序容器

本文详细介绍了C++标准库中容器的限制、操作、构造函数,特别是array、vector和string的使用细节。讨论了assign、swap函数、迭代器失效、容器增长策略以及resize和reserve的区别。同时,提到了容器适配器如stack、queue和priority_queue的实现方式。内容涵盖容器的安全操作、性能优化和内存管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 容器类型的限制

//假定noDefault没有默认构造函数
vector<noDefault> v1(10);			//错误,必须提供一个元素初始化器
vector<noDefault> v1(10,init);		//正确,可以自己提供元素初始化器

2.容器操作

//类型别名
difference_type		//带符号整数类型,足够保存两个迭代器之间的距离
//反向容器
reverse_iterator	//按逆序寻址元素的迭代器.(++是往前的)
c.rbegin(),  c.rend();	//尾元素和头元素之前位置的迭代器

3.迭代器转化

//非常量iterator可以转变为常量的iterator
list<string>::const_iterator it = a.begin();	//正确

4.容器构造函数

//迭代器初始化
C c(b,e);		//b和e都是迭代器.初始化的就是迭代器的内容;

5. array

1.初始化
array<int,10> a;		//a 是10个int型的数组(10个0)
array<string,10> a;		//a 是10个string型的数组

array<int,10> a{0,1,2,3,4,5,6,7,8,9};	//array存储从0~9
array<int,10> a{1}						//a[0] = 1,其它全0
2.可以拷贝
int digs[10] = {0,1,2,3,4,5,6,7,8,9};
int args[10] = digs;	//错误,内置数组不可拷贝

array<int,10> digs{0,1,2,3,4,5,6,7,8,9};
array<int,10> args = digs;		//正确,array可以拷贝赋值
3.(!!!primer错误!!!,现在已经可以)不能直接等于花括号序列
array<int,10> digs{0,1,2,3,4,5,6,7,8,9};
digs = {0,1};  //现在是正确的,因为array已经支持assign;
			   //digs = {0,1,0,0,0,0,0,0,0,0}

vector<int> t{ 1,2,3,4 };
t = { 0 };		//正确.因为可以用assign;

更新点:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OsVmw8Ie-1646145341261)(第九章 顺序容器.assets/image-20220228195950080.png)]

6. assign

//assign是直接删除原来的内容,再重新赋值
list<string> names{"a","b","c","d"};
vector<const char*> oldstyle;

oldstyle = names;	//错误,类型不匹配

vector<const char*> newstyle(names.begin(),names.end());		//正确
oldstyle.assign(names.begin(), names.end());					//正确,与上面等价

7. swap函数

swap需要注意不会去拷贝,复制数组中内容.只是交换了两个容器的内部数据结构.保证常数时间内完成

一般使用非成员函数的swap函数(算法库中)

8. 容器元素是拷贝来的

用一个对象初始化容器或者将一个对象插入到容器中,实际上放入到容器中的时对象值的一个拷贝

9. insert

insert(迭代器,个数,); //迭代器位置插入多少个值

10.下标操作和at

区别:

  1. at操作安全,下标操作越界时会直接报错.at在越界时返回一个out_of_range异常;
  2. 下标操作会比较快,因为at需要判断是否异常!

11.删除

//删除迭代器所指向的内容,均返回删除后的第一个元素位置迭代器
c.earse(p);		//p为迭代器
c.earse(b,e);	//删除b,e迭代器范围内的元素,左闭右开

12. resize() 和 reserve()区别

//共同的,都可以用来增大或者缩小容器.array不支持
/*
区别:
	1.resize()大小扩展到指定长度,然后在末尾补充0到添加的长度;如果容量太小也会进行扩充
	2.reserve()容量扩展到指定长度,但是不会添加0;而且size大小不变.
	
	删除:
	1.resize()如果变小,那么会删除大于指定长度之外的元素
	2.reserve()无法指定小于size(),即 容量 >= 大小是肯定的;
*/

vector<int> test{ 0,0,0,0,0,0,0 };
cout << test.size() << endl;		7
test.reserve(4);
cout << test.size() << endl;		7
test.resize(4);
cout << test.size() << endl;		4
    
//!记住,reverse不改变元素数量,但resize会!
    
    
//2.shrink_to_fit() 让 capacity = size.

13.迭代器失效

vector 和 string

  1. 容器重新分配空间,全部迭代器失效
  2. 容器插入一个元素,但是没有重新分配空间,那么就失效插入位置后的迭代器

list 和 forward_list

  1. 删除时除了直接指向的迭代器失效,其它均有效

deque

  1. 删除中间位置时,迭代器均失效.
  2. 删除头尾,其它迭代器有效

所以一般不要保存尾部迭代器.如果需要修改容器大小(插入,删除.resize),那么一定不要保存

14.vector的增长

如果resize 或 reserve时超出给定的 capacity.那么就会扩展,扩展的大小看具体实现(vs2017在第四次后时1.5倍速增长,gcc 5.4.0 2倍)

vector<int> a;
cout << a.capacity()<< endl;	//0	 最开始是0	
int num = 0;
int n = 10;
int *p = NULL;
while (n--)
{
    a.push_back(10);	
    cout << a.capacity()<< endl;	//1 2 3 4 6 6 9 9 9 13
    if (p != &a[0])					//前面线性增长,后面是1.5倍增长
    {
        p = &a[0];
        num++;
    }
}
cout << num << "次" << endl;		//7次

15.特殊的string函数

//构造函数
//还可以接受const char*. 位置为指针 + 数字
string s1 = ".....";
string s2(s1,pos2);		//s2字符串的值S1从下标pos2开始到结束
string s2(s1,pos2,len2)  //s2是字符串s1从下标pos2开始截取len2长度的字符串
    
//插入和删除

s.insert(s.size(),5,'!');	//在末尾插入五个'!';
s.insert(s.size() - 5,5);	//删除倒数5个字符;

//也可以接受const char*
const char*cp = "hello,world";
s.assign(cp,5);					//hello
s.insert(s.size(),cp + 5);  	//在hello后面插入,world;

16. substr 字符串截取

//从字符串中截取index下标开始,长度为len的字符串返回!长度默认值为 s.size() - index;
string temp = s.substr(index,len);

17. replace 字符串替换

s.replace(11,3,"5th");	//从第十一位开始替换3个字符为5th
//其实等价于
s.earse(11,3);
s.insert(11,3,"5th");

18. 字符串查找

//大小写敏感,任何一个查找都可以指定第二个参数pos,表示从pos位置开始寻找
str.find("str");		//找到返回开始位置,没找到就返回npos(str.npos);
str.find_first_of(num);	//查找在num字符串中任意一个字符第一次出现的下标;
str.find_last_of(num);	//查找在num字符串中任意一个字符最后一个出现的下标;
str.find_first_not_of(num); //查找第一个没出现在num字符串中的字符
str.find_last_not_of(num);	//查找最后一个没出现在num字符串中的字符

19.容器设配器

1.类型
  • ​stack 栈
  • queue 队列
  • priority_queue 优先队列
2.实现
  1. stack 可以用除了 forward_list 和 array外的其它容器来实现(需要back,push_back)

  2. queue 可以用 list 和 deque 来实现(需要front,back,push_back,pop_back,push_front,pop_front)

  3. priority_queue 可以 vector 和 deque来实现(需要 front,push_back和pop_back以及随机访问能力).

//一般情况下,stack 和 queue 基于 deque实现, 而priority_queue 基于 vector 实现;
//但是可以用顺序容器来修改默认值,比如指定用vector来实现stack
stack<int,vector<int>> stk;		//指定用vector实现的stack
priority_queue<int, vector<int>, greater<int>> que;	//小根堆,小的在上面
priority_queue<int, vector<int>, less<int>> que;	//大根堆,大的在上面
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公仔面i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值