【重温c++】快速回忆知识点其三

一、STL容器(上)

-string容器基础
string是字符容器,内部维护了一个动态的字符数组。
与普通的字符数组相比,string容器有三个优点:
1)使用的时候,不必考虑内存分配和释放的问题;
2)动态管理内存(可扩展);
3)提供了大量操作容器的API。缺点是效率略有降低。
-string容器的设计目标
string是什么?

  • 以字节为最小存储单元的动态容器。
  • 用于存放字符串(不存空字符0)。
  • 用于存放数据的内存空间(缓冲区)。

-string容器的操作
函数很丰富,在实际开发过程中,随用随百度;百度到的文章容易有错误,需要手动测试。
-vector容器
vector容器封装了动态数组。
分配器:各种STL容器模板都接受一个可选的模板参数,该参数指定使用哪个分配器对象来管理内存。
如果省略该模板参数的值,将默认使用allocator< T >,用new和delete分配和释放内存。
vector容器嵌套的结果像二维数组,但比二维数组更灵活;
二维数组的第二维大小是固定的,嵌套vector容器的第二维是可变的。
-迭代器
迭代器是访问容器中元素的通用方法。
如果使用迭代器,不同的容器,访问元素的方法是相同的。
迭代器支持的基本操作:赋值(=)、解引用(*)、比较(==和!=)、从左向右遍历(++)。
一般情况下,迭代器是指针和移动指针的方法。
迭代器有五种分类:
1)正向迭代器
语法:容器名<元素类型>::iterator 迭代器名;
2)双向迭代器
3)随机访问迭代器
4)输入和输出迭代器
-基于范围的for循环
对于一个有范围的集合来说,在程序代码中指定循环的范围有时候是多余的,还可能犯错误。
C++11中引入了基于范围的for循环。
语法:
for(迭代的变量:迭代的范围)
{
//循环体
}
注意:
1)迭代的范围可以是数组名、容器名、初始化列表或者可迭代的对象(支持begin()、end()、++、= =)。
2)数组名传入函数后,已退化为指针,不能作为容器名。
3)如果容器中的元素是结构体和类,迭代器变量应该声明为引用,加const约束表示只读。
4)注意迭代器失效的问题。

二、STL容器(下)

-list容器
使用迭代器。可以轻松地实现不同容器之前的转换。
-pair键值对
pair是类模板,一般用于表示key/value数据,其实现是结构体。
在这里插入图片描述
-红黑树(平衡二叉排序树)
左小右大。
-map容器(红黑树+pair键值对)
map容器封装了红黑树(平衡二叉排序树),用于查找。
在这里插入图片描述
注意:
[]运算符:如果指定键不存在,会向容器中添加新的键值对;如果指定键不存在,则读取或修改容器中指定键的值。
-哈希/散列表
在这里插入图片描述
-unordered_map容器(哈希表+pair键值对)
unordered_map容器封装了哈希表,查找、插入和删除元素时,只需要比较几次key的值。
在实际开发中,数据量如果只有几万,可以使用红黑树,如果达到了千万,则要使用哈希表。
在这里插入图片描述
-queue容器
queue容器的逻辑结构是队列,物理结构可以是数组或链表,主要用于多线程之间的数据共享。
-STL其它的容器
array(静态数组):
在栈上分配内存,创建数组的时候,数组长度必须是常量,创建后的数组大小不可变。
随机访问迭代器。
部分场景中,比常规数组更方便(能用于模板),可以取代常规数组。
deque(双端队列):
deque容器存储数据的空间是多段等长的连续空间构成,各段空间之间并不一定是连续的。
随机访问迭代器。
提高了在两端插入和删除元素的效率。
forward_list(单链表):
正向迭代器。
比双链表少了一个指针,可节省内存,减少了两次对指针的赋值操作。
multimap:
底层是红黑树。
multimap允许关键字重复,而map不允许重复。
set&multiset:
底层是红黑树。
map中存储的是键值对,set只保存关键字。
multset允许关键字重复,set不允许重复。
unordered_multimap:
底层是哈希表。
unordered_multimap允许关键字重复,unordered_map不允许重复。
unordered_set&unordered_multiset:
底层是哈希表。
unordered_map中存储的是键值对,unordered_set只保存关键字。
unordered_multiset允许关键字重复,unordered_set不允许重复。
priority_queue(优先队列):
优先级队列相当于一个有权值的单项队列queue,在这个队列中,所有元素是按照优先级排列的。
底层容器可以用deque和list。
stack(栈):
底层容器可以用deque和list。

三、STL算法

-STL算法for_each
for_each()函数将函数对象f用于[first,last]区间中的每个元素,它也返回f。
原理:遍历容器中的每个元素,在遍历的过程中,把每个元素的值作为实参调用程序员自定义的函数。
使用该函数需包含头文件 #include < algorithm>
-STL算法find_if
原理:遍历容器中的元素,在遍历的过程中,把元素的值作为参数传递给函数,如果函数返回值为true,则停止遍历。
使用该函数需包含头文件 #include < algorithm>
-STL算法sort
如果要使用STL提供的仿函数,要包含头文件#include < functional>
-STL算法总结
STL提供了很多处理容器的函数模板,它们设计是相同的,有以下特点:
1)用迭代器表示需要处理数据的区间。
2)返回迭代器放置处理数据的结果(如果有结果)。
3)接受一个函数对象参数(结构体模板),用于处理数据(如果需要)。

四、智能指针

-智能指针unique_ptr基础
智能指针设计思路:
1)智能指针是类模板,在栈上创建智能指针对象。
2)把普通指针交给智能指针对象。
3)智能指针对象过期时,调用析构函数释放普通指针的内存。
unique_ptr独享它指向的对象,也就是说,同时只有一个unique_ptr指向同一个对象,
当这个unique_ptr被销毁时,指向的对象也随即被销毁。
包含头文件:#include< memory>
在这里插入图片描述
-智能指针unique_ptr更多技巧
1)将一个unique_ptr赋给另一个时,如果源unique_ptr是一个临时右值,编译器允许这样做;
如果unique_ptr将存在一段时间,编译器禁止这样做。一般用于函数的返回值。
2)用nullptr给unique_ptr赋值将释放对象,空的unique_ptr==nullptr。
3)release()释放对原指针的控制权,将unique_ptr置为空,返回裸指针(可用于把unique_ptr传递给子函数,子函数将负责释放对象)。
4)std::move()可以转移对原始指针的控制权。(可用于把unique_ptr传递给子函数,子函数形参也是unique_ptr)
5)reset()释放对象。
6)swap()交换两个unique_ptr的控制权。
7)unique_ptr也可像普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样。
8)unique_ptr不是绝对安全,如果程序中调用exit()退出,全局的unique_ptr可以自动释放,但局部的unique_ptr无法释放。
9)unique_ptr提供了支持数组的具体化版本。
-智能指针shared_ptr
shared_ptr共享它指向的对象,多个shared_ptr可以指向(关联)相同的对象,在内部采用计数机制来实现。
在这里插入图片描述
注意:
1) shared_ptr支持赋值,左值的shared_ptr的计数器将减1,右值shared_ptr的计算器将加1。
2)如果 unique_ptr能解决问题,就不要用shared_ptr。unique_ptr的效率更高,占用的资源更少。
-智能指针的删除器
在默认情况下,智能指针过期的时候,用delete原始指针;释放它管理的资源。
程序员可以自定义删除器,改变智能指针释放资源的行为。
删除器可以是全局函数、仿函数和Lambda表达式,形参为原始指针。
-智能指针weak_ptr
weak_ptr是为了配合shared_ptr而引入的,它指向一个由shared_ptr管理的资源但不影响资源的生命周期。也就是说,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。
不论是否有weak_ptr指向,如果最后一个指向资源的shared_ptr被销毁,资源就会被释放。
在这里插入图片描述
多线程情况下:
在这里插入图片描述

五、文件操作

在这里插入图片描述
-文件操作-写入文本文件
在这里插入图片描述
在这里插入图片描述
-文件操作-读取文本文件
在这里插入图片描述
-文件操作-写入二进制文件
1) 打开文件时,添加枚举常量指定为打开二进制文件。
在这里插入图片描述
2)写入数据时,要用输出流ofstream的write()成员函数。
在这里插入图片描述
-文件操作-读取二进制文件
在这里插入图片描述
-文件操作-更多细节
1)在windows平台下,文本文件的换行标志是“\r\n”。
2)在Linux平台下,文本文件的换行标志是“\n”。
3)在windows平台下,如果以文本方式打开文件,写入数据的时候,系统会将“\n”转换成“\r\n”;
读取数据的时候,系统会将“\r\n”转换成“\n”。如果以二进制方式打开文件,写和读都不会进行转换。
4)在Linux平台下,以文本或二进制方式打开文件,系统不会做任何转换。
5)以文本方式读取文件的时候,遇到换行符停止,读入的内容中没有换行符;
以二进制方式读取文件的时候,遇到换行符不会停止,读入的内容中会包含换行符(换行符被视为数据)。
6)在实际开发中,
(a)以文本模式打开文本文件,用行的方法操作它;
(b)以二进制模式打开二进制文件,用数据块的方法操作它;
(c)以二进制模式打开文本文件和二进制文件,用数据块的方法操作它,这种情况表示不关心数据的内容。
-文件操作-fstream类
在这里插入图片描述
-文件操作-随机存取
文件的位置指针:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
随机存取 :
指直接移动文件的位置指针,在指定位置读取/写入数据。
-文件操作-缓冲区和流状态
文件缓冲区:
文件缓冲区是系统预留的内存空间,用于存放输入或输出的数据。
在C++中,每打开一个文件,系统就会为它分配缓冲区。不同的流,缓冲区是独立的
程序员只需要关心输出缓冲区
1)flush():刷新缓冲区
2)endl:换行,然后刷新缓冲区
3)unitbuf:设置fout输出流,在每次操作之后自动刷新缓冲区。
4)nounitbuf:设置fout输出流,让fout回到缺省的缓冲方式。
流状态:
在这里插入图片描述

六、C++异常与断言

-C++异常
C++11已弃用,因为如果程序中的异常没有被捕获,程序将异常中止。
语法:try{//抛出异常} catch(…){//处理异常}
-如何避免异常
1)std::bad_alloc:如果内存不足,调用new会产生异常,导致程序中止;如果在new关键字后面加(std::nothrow)选项,则返回nullptr,不会产生异常。
2)std::bad_cast:dynamic_cast可以用于引用,但是,没有与空指针对应的引用值,如果转换请求不正确,会出现该异常。
3)std::bad_typeid:假设有表达式typeid(*ptr),当ptr是空指针时,如果ptr是多态的类型,将引发该异常。
-C++断言
断言(assertion)是一种常用的编程手段,用于排除程序中不应该出现的逻辑错误。
语法:assert(表达式);
注意:
1)断言用于处理程序中不应发生的错误,而非逻辑上可能会发生的错误。
2)不要把需要执行的代码放在断言的表达式中。
3)断言的代码一般放在函数/成员函数的第一行,表达式多为函数的形参。
在这里插入图片描述

七、C++新标准

-委托构造和继承构造
委托构造就是在一个构造函数的初始化列表中调用另一个构造函数。
注意:
1)不要生成环状的构造过程。
2)一旦使用委托构造,就不能在初始化列表中初始化其它的成员变量。
继承构造,在派生类中使用using来声明继承基类的构造函数。
-lambda函数
lambda函数也称lambda表达式或匿名函数。
在这里插入图片描述
在这里插入图片描述
-右值引用
在这里插入图片描述
在这里插入图片描述
引入右值引用的主要目的是实现移动语义。
-移动语义
在这里插入图片描述
如果形参是左值,就调用普通赋值函数;如果形参是右值,就调用移动赋值函数。
-完美转发
在这里插入图片描述
在这里插入图片描述
-可变参数模板
可变参数模板是C++新增的最强大的特性之一,它对参数进行了泛化,能支持任意个数、任意数据类型的参数。
在这里插入图片描述
-时间操作
在这里插入图片描述
1)时间长度
在这里插入图片描述
2)系统时间
在这里插入图片描述

3)计时器
在这里插入图片描述

八、C++线程

点击跳转

九、可调用对象的绑定器和包装器

点击跳转

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值