1. 顺序容器

  • vector和string将元素保存在连续的内存空间中。由于元素是连续存储的,由元素的下标来计算其地址是非常快速的。但是在这两种容器的中间位置添加或删除元素就非常耗时
  • list和forward_list两个容器的设计目的是令容器任何位置的添加和删除操作都很快速。作为代价,这两个容器不支持元素的随机访问
  • deque是一个更为复杂的数据结构。与string和vector类似,deque支持快速的随机访问。在deque的中间位置添加或删除元素的代价(可能)很高。但是,在deque的两端添加或删除元素都是很快的,与list和forward_list添加删除元素的速度相当
  • forward_list没有size操作

1.1 容器的定义和初始化

  每个容器类型都定义了一个默认构造函数。除array之外,其他容器的默认构造函数都会创建一个指定类型的空容器,且都可以接受指定容器大小和元素初始值的参数。

  

 

1.1.1 将一个容器初始化为另一个容器的拷贝

  主要有两种方式,①直接拷贝整个容器,②(array除外)拷贝由一个迭代器对指定的元素的范围。

 #include<vector>
#include<string>
#include<deque>
#include<forward_list>
#include<list>
#include<iostream>
using namespace std; int main() {
list<string> authors = { "tom", "Mike", "Bob" };
vector<const char*> articles = { "ad", "mi" ,"po" }; list<string> authors2(authors);
//vector<string> articles2(articles);//错误,类型不一致 /*forward_list
单向list,不能反向迭代(list可以)
不能使用size函数,但是可以使用迭代器的distance来计算
但是
forward_list的操作比list容器块,且内存占用少
*/ forward_list<string> articles3(articles.begin(), articles.end());
cout << distance(articles3.begin(), articles3.end()) << endl; // 3d getchar();
return ;
}

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

  只有顺序容器的构造函数才接受大小参数,关联容器不支持。

 vector<int> ivec (, -);    //10个int元素,每个都初始化为-1
list<string> svec(,"hi"); //10个string,每个够初始化为“hi"
forward_list<int> ivec(); //10个元素,每个都初始化为0
deque<string> svec(); //10个元素,每个都是空string

1.1.3 标准库array具有固定大小

  array 是提供的新容器,比内置数组更安全。两者一定区别如下:

 // 内置数组初始化
int a[];
int b[] = { ,, };
int c[] = { ,, };//其他值默认初始化 0
// 访问数组下标时,可以非 size_type 类型,只要不越界。但是容器不行
int *ptr = &a[];
cout << ptr[-] << endl; // 数组容器
array<int, > a1;
array<int, > b1 = { ,,, };
// 但是容器能拷贝复制,只要容器 类型+大小 一致
array<int, > c1 = b1;
//a1 = b1; //但是不能直接拷贝
// 容器的遍历遵循普通容器遍历方式

1.2 顺序容器操作

1.2.1 向顺序容器添加元素

  • push_back : 除了array 和 forward_list 之外,每个顺序容器(包括string 类型),都支持
  • 除了push_back之外,listforward_listdeque 还支持名为 push_front 的操作
  • 在容器特定位置添加元素:

  vecotr,deque,list,string 支持 insert(iter, value) 的操作(forward_list 有自己的 insert 的操作),所以,即使 vector 没有 push_front 操作,但是可:

 vector<string> vct;
vct.insert(vct.begin(), "test"); // vector 不插入末尾,则效率很慢
  • 插入范围元素:
// 接受一个元素数目和元素值
vct.insert(vct.end(), , "qaq"); //在end处插入,个数为4,初始化为qaq的字符串 // 接受一对迭代器
vct.insert(vct.end(), vct2.end() - , vct2.end());//插入位置,vct2给定范围 // 接受位置和列表
vct.insert(vct.end(), { "", "xswl" }); // 插入的列表不能指向目标容器
// vct.insert(vct.end(), vct.begin(), vct.end()); // 错误
  • 使用 insert 的返回值。insert 返回值为指向这个新元素
 list<string> lst;
auto iter = lst.begin();
while (cin >> word)
iter = lst.insert(iter, word); //等价于调用push_front
  • emplace
 //在c的末尾构造一个Sales_data对象
//使用三个参数的Sales_data构造函数
c.emplace_back("978-9897897987", , 15.99);
//错误:没有接受三个参数的push_back版本
c.push_back("978-9897897987", , 15.99);
//正确:创建一个临时的Sales_data对象传递给push_back
c.push_back(Sales_data("978-9897897987", , 15.99));

1.2.2 访问元素

 包括 array 在内的每个顺序容器中,都有一个 front 成员函数,而除 forward_list 之外,所有顺序容器都有 back 成员函数。 

 // 解引用一个迭代器时,要判空
if (!lst.empty()) {
auto val1 = *lst.begin(), val2 = lst.front(); auto last = lst.end();
auto val3 = *(--last);// forward_list 迭代器不能递减
auto val4 = lst.back();// forward_list 不支持
}

  下面再看:

 /*
front back 都是返回引用
*/ int main() { // 数组容器
array<int, > a1;
array<int, > b1 = { ,,, }; b1.front() = ; // b1 初始值改变
int &c = b1.back();
c = ; // b1 末尾值改变 // auto 会吃引用
auto a2 = a1.front();
a2 = ; // 无效,可通过 auto &a2 getchar();
return ;
}

1.2.3 删除元素

  vector 和 string 不支持 push_front 所以不支持 pop_front。同时 vct.clear() 等同于 vct.erase(vct.begin(), vct.end())。

  

1.2.4 删除插入更新迭代器

  insert 之后返回的是新插入的元素的迭代器,erase之后返回的是被删除的后一个元素的迭代器(此时注意end)。

 int main() {
// 删除所有偶数元素,复制所有奇数元素
vector<int> v = { ,,,,,,,,, };
auto iter = v.begin(); while (iter != v.end()) {
if (*iter % ) {
iter = v.insert(iter, *iter);
iter += ;
}
else {
iter = v.erase(iter);
}
} getchar();
return ;
}

  不要保存容器的end迭代器,当容器增加或者删除元素时,end迭代器也会失效,所以应该通过 v.end() 来判断,而不应保存至某一个局部变量。

  

1.2.5 构造 string 的其他方法

  

 int main() {
char ch[] = { 'a','b','c','','' };//不空字符结尾
string s(ch, );
cout << s << endl; //abc12 string s2(s, ); // (string,pos) 从pos位置开始拷贝
cout << s2 << endl;// bc12 string s3(s, , ); // (string,start,length)
cout << s3 << endl; // bc /*
通常当我们从一个 const char* 创建 string 时,指针指向的数组必须以空字符('/0')结尾,拷贝
操作遇到空字符时停止。
如果我们传递给构造函数拷贝长度,则无所谓
*/
const char *cc = "qaq23333";//以空字符结尾
string s4(cc);
string s5(ch); // ch 不是以空字符结尾,即未定义 cout << s4 << "\t" << s5 << endl;//打印s5出现奇怪字符 getchar();
return ;
}

1.2.6 string操作——substr,insert,erase

 #define Log(s) cout << s << endl;
int main() { string str("233qaq"); /// substr
string s2 = str.substr();
Log(s2); // 3qaq
s2 = str.substr(, );
Log(s2);// /// insert
str.insert(, s2); // 下表版本插入
Log(str); //23233qaq
str.insert(str.end(), 'h');// 迭代器版本插入
Log(str); //23233qaqh
str.insert(, s2, , );// 插入3
Log(str); //33233qaqh
str.insert(, "hi");
Log(str); //hi33233qaqh /// erase
string str("This is an example sentence.");
str.erase(, ); // 从下标10开始,erase 8位
Log(str); // "This is an sentence."
str.erase(str.begin() + ); // begin迭代器开始第九位
Log(str); // "This is a sentence."
str.erase(str.begin() + , str.end() - );
Log(str)// "This sentence." getchar();
return ;
}

1.2.7 string操作——append,replace

 #define Log(s) cout << s << endl;
int main() {
string s("hello"), s2 = s;
s.insert(s.size(),",world");
s2.append(",world"); // 同上,效果一致
Log(s);
Log(s2); s.erase(, ); // 从下标5开始,erase 6 位
s.insert(, ",Bob");
s2.replace(, , ",Bob"); // 效果同上两句话一致
Log(s);
Log(s2); getchar();
return ;
}

c++基础(三)——容器的更多相关文章

  1. Bootstrap <基础三十>Well

    Well 是一种会引起内容凹陷显示或插图效果的容器 <div>.为了创建 Well,只需要简单地把内容放在带有 class .well 的 <div> 中即可.下面的实例演示了 ...

  2. Python全栈开发【基础三】

    Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...

  3. Bootstrap <基础三十二>模态框(Modal)插件

    模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 如果您想要单独引用该插件的功能,那么您需要引用  ...

  4. Bootstrap <基础三十一>插件概览

    在前面布局组件中所讨论到的组件仅仅是个开始.Bootstrap 自带 12 种 jQuery 插件,扩展了功能,可以给站点添加更多的互动.即使不是一名高级的 JavaScript 开发人员,也可以着手 ...

  5. Bootstrap<基础三> 排版

    Bootstrap 使用 Helvetica Neue. Helvetica. Arial 和 sans-serif 作为其默认的字体栈. 使用 Bootstrap 的排版特性,您可以创建标题.段落. ...

  6. jdbc基础 (三) 大文本、二进制数据处理

    LOB (Large Objects)   分为:CLOB和BLOB,即大文本和大二进制数据 CLOB:用于存储大文本 BLOB:用于存储二进制数据,例如图像.声音.二进制文件 在mysql中,只有B ...

  7. Ruby语法基础(三)

    Ruby语法基础(三) ​ 在前面快速入之后,这次加深对基本概念的理解. 字符串 ​ Ruby字符串可以分为单引号字符串和双引号字符串,单引号字符串效率更高,但双引号的支持转义和运行 puts '单引 ...

  8. C#_02.13_基础三_.NET类基础

    C#_02.13_基础三_.NET类基础 一.类概述: 类是一个能存储数据和功能并执行代码的数据结构,包含数据成员和函数成员.(有什么和能够干什么) 运行中的程序是一组相互作用的对象的集合. 二.为类 ...

  9. 04 mysql 基础三 (进阶)

    mysql 基础三 阶段一 mysql 单表查询 1.查询所有记录 select * from department; ​ select * from student; ​ select * from ...

  10. Python 基础 三 反射

    Python 基础 三 反射 今天我们先介绍一下反射这个概念,啥是反射?反射就是自己检测自己.在我们Python的面向对象中的反射是啥意思呢?就是通过字符串的形式操作对象相关的属性.python中的一 ...

随机推荐

  1. Logistic Regression Algorithm

    逻辑回归算法LR. 简介 逻辑回归是机器学习从统计学领域借鉴的另一种技术.它是二进制分类问题的首选方法(有两个类值的问题).   Logistic回归就像线性回归,目标是找到权重每个输入变量的系数值. ...

  2. hasura skor 构建安装

    hasura skor 前边有介绍过是一个挺不错的event trigger 插件,我们可以用来进行事件通知处理 官方有提供构建的方法,但是有些还是会有点问题,所以结合构建碰到的问题,修改下 clon ...

  3. Mac OSX上安装SublimeText 3编译Processing 3.0

    1.安装SublimeText 32.使用Preferences - Package Control:Install Package - Processing安装 如果移动了Processing的位置 ...

  4. hhhhh我进步啦!

    不要相信上面的标题,其实我是 一直都很强的 蒟蒻中的蒟蒻(卑微☹) 今天早上刷完水题后突然发现自己竟然进了一本通网站“排名”的首页(第 100 名欸),不禁 嘚瑟 开森不已. ☟☟☟ 继续A题↖(^ω ...

  5. EasyEarth三维可视化解决方案——智慧园区

    智慧园区 智慧园区围绕“园区行为数据化”和“园区数据可视化”的核心理念,依托EasyEarth三维可视化基础地理信息云平台,综合运用云计算.物联网.自动化控制.现代通讯.图像识别.软硬件集成等技术,借 ...

  6. samba-centos7

    目的: 1,匿名访问共享目录/home/home and /home/share 2,/home/samba/home 共享名为home,有读写权限,但是进入该文件夹需要验证用户 3,/home/sa ...

  7. SpringBoot框架 之 Druid与Swagger2

    目录 Druid Druid连接池配置 Druid数据监控 集成Swagger2 Swagger2简介 1.添加依赖 2.创建Swagger2配置类 3.在控制器方法上添加对应api信息 4.启动Sp ...

  8. Alpha3

    队名:福大帮 组长博客链接:https://www.cnblogs.com/mhq-mhq/p/11899921.html 作业博客 :https://edu.cnblogs.com/campus/f ...

  9. 剑指offer:和为S的连续正数序列

    题目描述: 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久, ...

  10. elastic stack安装运行(docker)

    https://www.docker.elastic.co 注:目前阿里云为7.4 elasticsearch 参考https://www.elastic.co/guide/en/elasticsea ...