c++基础(三)——容器
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之外,list、forward_list、deque 还支持名为 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++基础(三)——容器的更多相关文章
- Bootstrap <基础三十>Well
Well 是一种会引起内容凹陷显示或插图效果的容器 <div>.为了创建 Well,只需要简单地把内容放在带有 class .well 的 <div> 中即可.下面的实例演示了 ...
- Python全栈开发【基础三】
Python全栈开发[基础三] 本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...
- Bootstrap <基础三十二>模态框(Modal)插件
模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 如果您想要单独引用该插件的功能,那么您需要引用 ...
- Bootstrap <基础三十一>插件概览
在前面布局组件中所讨论到的组件仅仅是个开始.Bootstrap 自带 12 种 jQuery 插件,扩展了功能,可以给站点添加更多的互动.即使不是一名高级的 JavaScript 开发人员,也可以着手 ...
- Bootstrap<基础三> 排版
Bootstrap 使用 Helvetica Neue. Helvetica. Arial 和 sans-serif 作为其默认的字体栈. 使用 Bootstrap 的排版特性,您可以创建标题.段落. ...
- jdbc基础 (三) 大文本、二进制数据处理
LOB (Large Objects) 分为:CLOB和BLOB,即大文本和大二进制数据 CLOB:用于存储大文本 BLOB:用于存储二进制数据,例如图像.声音.二进制文件 在mysql中,只有B ...
- Ruby语法基础(三)
Ruby语法基础(三) 在前面快速入之后,这次加深对基本概念的理解. 字符串 Ruby字符串可以分为单引号字符串和双引号字符串,单引号字符串效率更高,但双引号的支持转义和运行 puts '单引 ...
- C#_02.13_基础三_.NET类基础
C#_02.13_基础三_.NET类基础 一.类概述: 类是一个能存储数据和功能并执行代码的数据结构,包含数据成员和函数成员.(有什么和能够干什么) 运行中的程序是一组相互作用的对象的集合. 二.为类 ...
- 04 mysql 基础三 (进阶)
mysql 基础三 阶段一 mysql 单表查询 1.查询所有记录 select * from department; select * from student; select * from ...
- Python 基础 三 反射
Python 基础 三 反射 今天我们先介绍一下反射这个概念,啥是反射?反射就是自己检测自己.在我们Python的面向对象中的反射是啥意思呢?就是通过字符串的形式操作对象相关的属性.python中的一 ...
随机推荐
- JavaScript基础05——严格模式
严格模式: 除了正常运行模式,ECMAscript5添加了第二种运行模式:“严格模式”(strict mode).顾名思义,这种模式是的Javascript在更严格的条件下运行. 严格模式的作用: 1 ...
- webpack的loader的原理和实现
想要实现一个loader,需要首先了解loader的基本原理和用法. 1. 使用 loader是处理模块的解析器. module: { rules: [ { test: /\.css$/, use: ...
- Xamarin.Forms 入门
介绍 Xamarin.Forms是一个开源UI框架,Xamarin.Forms允许开发人员从单个共享代码库构建Android,iOS和Windows应用程序. Xamarin.Forms允许开发人员使 ...
- Call to undefined function imagecreatefromjpeg() 让GD支持JPEG格式的图片扩展
安装扩展支持jpeg格式: 第一步:首先下载文件: 版本v8: wget http://www.ijg.org/files/jpegsrc.v8b.tar.gz 版本v9: wget http://w ...
- 洛谷 P2085 最小函数值
目录 题目 思路 \(Code\) 题目 戳 思路 首先这些函数全部单带递增,因为\(a\),\(b\),\(c\)都是正整数. 我们将全部的函数的\(x\)为\(1\)时的函数值放入优先度列(小根堆 ...
- vim配置无插件
其实,vim插件会影响编辑器的启动速度,虽然有些插件影响不大,我依然觉得不够,其实通过简易的状态栏,可以显示必要的信息,能自定义颜色和背景甚至透明就足够了. 一.自定义状态栏其实以下内容可以写在一行上 ...
- 检测算法简介及其原理——fast R-CNN,faster R-CNN,YOLO,SSD,YOLOv2,YOLOv3
1 引言 深度学习目前已经应用到了各个领域,应用场景大体分为三类:物体识别,目标检测,自然语言处理.本文着重与分析目标检测领域的深度学习方法,对其中的经典模型框架进行深入分析. 目标检测可以理解为是物 ...
- 公司不用 Spring Boot,果断离职了!
面试问到离职原因,我想这是很多面试者的痛,包括我自己,曾经也被离职原因所坑过. 面试回答离职原因简直特么就是巨坑,我也因此在微信公众号 "Java技术栈" 写了这篇文章<过了 ...
- [Web 安全] WASC 和 OWASP两个web安全方面组织机构介绍
copy from : http://blog.sina.com.cn/s/blog_70b7aab9010126mn.html WASC 和 OWASP.这两个组织在呼吁企业加强应用安全意识和指导 ...
- Linux Shell 之 对文件中的行、单词、字符进行迭代
在进行文本文件进行处理时,对文件件中的行.单词.字符进行迭代和遍历是非常常用的操作.而将一个简单的循环用于迭代,再加上来自stdin或文件的重定向,这就是对文件中的行.单词.和字符进行迭代的基本方法. ...