C++Primer笔记-----day07
==========================================================================
day07
==========================================================================
1.io对象不能拷贝或赋值,进行io操作的函数,通常以引用方式传递和返回流。读写一个io对象会改变其状态,所以传递和返回的引用不能是const的。
2.【在使用基类对象的地方,可以用子类对象来代替】。
==========================================================================
vector介绍
1.vector用于操作大小的函数有size(),max_size(),capacity().
size()返回当前vector中的元素个数。可通过resize(n)函数改变其值,即将元素数量改为n。
max_size()返回vector能够容纳的最大元素数量,其值因vector实现的版本而异。
capacity()返回vector中实际能容纳的元素数量。可通过reserve(n)函数改变其值,即预留n个内存。
2.当我们对容器赋值元素时,源容器的所有元素被拷贝到目标容器中,目标容器中原来的所有元素全被移除。所以,容器的赋值操作代价比较昂贵。
如果两个容器类型相同,而且拷贝后源容器不再被使用,我们可以用一个简单的优化方法,swap()。 dst.swap(src)。
swap()的性能比赋值高的多,因为它只交换容器内部数据,事实上,它只交换某些内部指针。时间复杂度为常数。
注意:swap交换内容后,两个容器的容量也会互换。所以可以这样缩减一个vector的容量:
template<class T>
void shrinkCapacity(vector<T>& v)
{
vector<T> temp(v);
v.swap(temp);
}
3.vector的容量很重要,因为:
(1)一旦内存重新配置,和vector元素相关的指针、引用、迭代器都会失效。
(2)内存的重新配置很耗时。
所以,当我们的程序管理了vector元素相关的针、引用、迭代器,或者程序的效率要求很高时,就必须考虑容量问题了。
一种方法是,可以使用reserve()保留适当的容量,避免容量不足时重新分配内存。这样,只要保留的容量尚有余裕,我们就不用担心引用失效了。
4.注意,迭代器支持的算术操作 iter1 - iter2 iter1+n <=、>=、>、< 只可以用于string、vector、deque、array。 因为他们在内存中的空间是连续的,
而像list就不可以使用这些算术操作。
eg: list<int> lst1;
auto iter1 = lst1.begin();
auto iter2 = lst1.end();
while(iter1<iter2) {/*....*/} // 错误,list不支持 < 操作
5.array中,大小也是其类型的一部分。如array<int,10>
标准array具有固定大小,初始化array时,元素数目必须小于或等于其大小,如果小于,则剩余元素默认初始化。
不用于数组,一个array可以拷贝给另一个array,但两个array必须是相同类型(包括大小,大小也是其类型的一部分)。
注意:array不支持赋值操作assign。因为右边的对象可能与左边的对象大小不相等。
6.swap即提供了成员函数的版本,又提供了非成员版本。 统一使用非成员版本的swap是一种好习惯。
7.insert函数的功能是在容器的某个迭代器位置【前】插入一个或多个元素。为什么是在迭代器之前呢?这是因为迭代器可能指向的是容器尾部不存在的元素的位置。
四种insert:
c.insert(it,"hello"); //在指定位置插入一个元素
c.insert(it,10,"A"); //在指定位置插入多个元素,并初始化为A
c.insert(it,v.begin(),v.end()); //将一个范围内的元素插入it之前
c.insert(it,{"abc","def"}); // 使用初始化列表来插入
insert函数的返回值,其返回第一个新加入元素的迭代器。利用这一点,可以在某个特定位置反复插入。
8.新标准下引入的emplace_front、emplace、emplace_back分别对应于push_front、insert、push_back。
它们的区别在于,调用push和insert时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中,
而调用emplace时,将参数传递给元素类型的构造函数,emplace使用这些参数在容器管理的内存空间直接构造元素。
eg: vector<PersonInfo> c; //假设PersonInfo类型有默认构造函数
c,emplace_back(); // 使用PersonInfo的默认构造函数,将一个元素添加到容器中
c.emplace_back("Jack",22,"15110634483");
c.push_back("Jack",22,"15110634483"); //错误,没有接受三个参数版本的push_back
c.push_back(PersonInfo("Jack",22,"15110634483")); //正确,创建一个临时PersonInfo对象传递给push_back
9. 访问容器中的元素:
每个顺序容器都定义了front(),除forward_list外,都定义了back()。
对于string、vector、deque、array,还可以使用下标运算符[]和at()来访问容器中的元素。
注意:front()、back()、[]、at()返回的都是引用!如果容器是一个const对象,则返回const引用,如果不是,则返回普通引用。
eg: vector<int> a(10,5);
a.front() = 5; // 将5赋给a中的第一个元素
auto v = a.front(); // v不是一个引用,它是a.front()的一个拷贝
v = 20; // a.front的值没有被改变
auto &v2 = a.front(); // v2是一个引用,他将改变a.front的值
v2 = 30;
10. 删除容器中的元素: pop_front()、pop_back()、erase()、clear()
vector、string不支持pop_front(),forward_list不支持pop_back(),而且他还有特殊版本的erase
其中pop操作、clear()返回void,而erase()返回被删除的最后一个元素之后的迭代器。
11. 对于forward_list,它有自己的插入,删除操作。它是一个单链表,这些操作的前提是要知道访问结点的前驱结点。
于是,它定义了before_begin(),cbefore_begin()返回首前迭代器,即首元素之前的不存在的元素的迭代器。
insert_after() 返回最后一个插入元素的迭代器
emplace_after() 返回指向新元素的迭代器
erase_after() 返回被删除元素之后元素的迭代器
12.增删元素都可能使得迭代器失效。这时,为保证后续迭代器不失效,应该这样做:
eg:vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto iter = vi.begin();
while(iter!=vi.end()){
if(*iter%2){
iter = vi.insert(iter,*iter); // 如果为奇数,复制当前元素
iter += 2; // 为保证后续迭代器有效,向前移动迭代器,跳过当前元素和插入到它之前的元素
}else{
iter = vi.erase(iter); // 删除偶数元素
// 此时不需要移动迭代器,因为erase返回的就是我们删除的元素之后的元素
}
}
此代码还有一处重点需要注意: while(iter!=vi.end()) 循环判断条件必须每次都调用vi.end(),
而不能这样: auto e = vi.end();
while(iter!=e){/*...*/} // 因为每次增删元素都会使得尾置迭代器失效,必须重新获取!
13. 顺序适配器 stack、queue、priority_queue
stack和queue默认是基于deque实现的,而priority_queue是基于vector实现的
C++Primer笔记-----day07的更多相关文章
- C++ Primer笔记
C++ Primer笔记 ch2 变量和基本类型 声明 extern int i; extern int i = 3.14;//定义 左值引用(绑定零一变量初始值,别名) 不能定义引用的引用:引用必须 ...
- C++ Primer 笔记(1)基础中的战斗机 输入输出 对输入不定数据处理
今天打算再重新好好的看一遍C++ Primer这本很经典的书籍,笔记开始: 1.每个C++程序都包含一个或者多个函数,其中必须有一个main,操作系统通过调用main入手运行程序: 2.函数包括:返回 ...
- C++ Primer 笔记 第一章
C++ Primer 学习笔记 第一章 快速入门 1.1 main函数 系统通过调用main函数来执行程序,并通过main函数的返回值确定程序是否成功执行完毕.通常返回0值表明程序成功执行完毕: ma ...
- C++primer笔记之顺序容器
最近又重新拾起C++primer,发现每一次看都会有不同的体验,但每一次看后因为不常用,忘记得很快,所以记笔记是很关键的一环,咋一看是浪费时间,实际上是节省了很多时间.下面就把这一节的内容做一个简单的 ...
- c++ primer 笔记 (一)
昨天开始看的<C++ Primer>,确实不错.希望这周抓紧看完,每天做下笔记,以便以后复习. main函数返回一个值给操作系统 操作系统通过main函数返回的值来确定程序是否成功执行 ...
- C++ Primer笔记(1)——连续读取数据、类型对应的尺寸、类型转换、字符串分行写法
这次要看看C++ Primer,这本基本上就是必读书籍了.下面的内容就是一些之前没有学过的知识的笔记. 读取数量不定的输入数据 虽然很简单,但是还是记一下: #include <iostream ...
- C++Primer笔记(3)
标准库类型string表示可变长的字符序列,使用前先包含string头文件.(哈哈,终于可以逃脱C语言中的str函数系列了.)因为是标准库的一部分,所以string被定义在命名空间std中.所以你懂该 ...
- C++ Primer 笔记 第三章
C++ Primer 第三章 标准库类型 3.1using声明 例: using namespace atd; using std::cin; 3.2string类型 初始化方式 string s1 ...
- C++ Primer 笔记 第二章
C++ Primer 第二章 变量和基本类型 2.1基本内置类型 有算数类型和void类型:算数类型储存空间大小依及其而定. 算数类型表: 类型 含义 最小储存空间 bool 布尔型 - char 字 ...
随机推荐
- @Resource、@Autowired、@Qualifier 区别(表格显示)
@Resource.@Autowired.@Qualifier 区别(表格显示) 区别项 @Resource @Autowired @Qualifier 谁提供的 jdk提供,包是javax.anno ...
- Win7 搭建pptpvpn服务器方法
打开网络与共享中心 选择更改适配器设置 选择菜单文件选项(若无菜单栏,可以按一下alt键就会显示出来的) 选择新建传入链接 选择需要哪些用户可以访问vpn服务器,把勾搭上,点击下一步 注意此处的通过i ...
- 如何使用swingbench进行oracle数据库压力测试
如何使用swingbench进行oracle数据库压力测试 2014-10-06 08:09:02 标签:oracle 数据库压力测试 swingbench 原创作品,允许转载,转载时请务必以超链接形 ...
- Vs2008应用程序升级为vs2012
Vs2008应用程序升级为vs2012 编写人:左丘文 2015-5-21 近来一直有想法,想将开发环境升级 vs2008到vs2012,在此做个小结,将自己碰到的一系统问题,分享出来,以供参考.有兴 ...
- 1、zookeeper集群安装
前提准备3台centos7.0虚拟机 c7003:192.168.70.103 c7004:192.168.70.104 c7005:192.168.70.105 并在三台虚拟机上配置hosts为 1 ...
- C#操作VFP的dbf数据库文件实例
C#操作VFP的dbf数据库文件实例 新一篇: js获取网站跟路径 实例中分别使用Oledb和Odbc操作vfp数据库dbf文件,操作包括:读取,增删改. 已测试可直接使用,使用方法:下面代码分两个部 ...
- a标签不用点击模拟跳转url。
因为请求到数据前要判断用户是否是登录状态, 所以就想页面数据请求成功,就跳转到登录页面, 就用了location.href = url. 结果因为同源策略不能访问, 没想到a标签竟然可以直接跳转这个U ...
- win7一键拖动生成快速启动栏
一键拖动生成快速启动工具栏 ^#x:: ;自动添加快速启动工具栏 if had_added() ExitApp ql_add() Sleep, if (is_locked()) { lock_unlo ...
- Qt5布局管理(一)——QSplitter分割窗口类
转载:LeeHDsniper 概述 本文首先通过三个实例分别介绍Qt5的分割窗口QSplitter类.停靠窗口QDockWidget类.堆栈窗体QStackedWidget类,然后介绍布局管理器的使用 ...
- [UE4]让AI跑起来
让AI由静止状态变成跑步状态,做法跟玩家角色走路一样. 一.创建1D混合动画 二.在AI角色关联的动画蓝图中使用第一步创建的混合动画