1.什么是标准库(STL)?
C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量、链表、队列、栈。
2.C++ 标准模板库的核心三个组件组成?
3.string
C++ 从 C 继承的字符串概念仍然是以 '\0' 为结束符的 char 数组。C++ 标准库中的 string class 可以将 string 作为一个型别,可以实现复制、赋值和比较,不必担心内存大小及占用内存实际长度等具体问题。
STL 中只有一个字符串类,即 basic_string。类 basic_string 实现管理以 \0
结尾的字符数组,字符类型由模板参数决定。要使用 string 类,必须包含头文件 <string>。在 STL 库中,basic_string 有两个预定义类型:包含 char 的 string 类型和包含 wchar 的 wstring 类型。
(1)string 类提供的各种操作函数大致分为八类:构造器和析构器、大小和容量、元素存取、字 符串比较、字符串修改、字符串接合、I/O 操作以及搜索和查找。
string 类的所有成员函数
函数名称 | 功能 |
---|---|
构造函数 | 产生或复制字符串 |
析构函数 | 销毁字符串 |
=,assign | 赋以新值 |
Swap | 交换两个字符串的内容 |
+ =,append( ),push_back() | 添加字符 |
insert () | 插入字符 |
erase() | 删除字符 |
clear () | 移除全部字符 |
resize () | 改变字符数量 |
replace() | 替换字符 |
+ | 串联字符串 |
==,! =,<,<=,>,>=,compare() | 比较字符串内容 |
size(),length() | 返回字符数量 |
max_size () | 返回字符的最大可能个数 |
empty () | 判断字符串是否为空 |
capacity () | 返回重新分配之前的字符容量 |
reserve() | 保留内存以存储一定数量的字符 |
[],at() | 存取单一字符 |
>>,getline() | 从 stream 中读取某值 |
<< | 将值写入 stream |
copy() | 将内容复制为一个 C - string |
c_str() | 将内容以 C - string 形式返回 |
data() | 将内容以字符数组形式返回 |
substr() | 返回子字符串 |
find() | 搜寻某子字符串或字符 |
begin( ),end() | 提供正向迭代器支持 |
rbegin(),rend() | 提供逆向迭代器支持 |
get_allocator() | 返回配置器 |
(2) string构造函数和析构函数详解
//构造函数
string strs //生成空字符串
string s(str) //生成字符串str的复制品
string s(str, stridx) //将字符串str中始于stridx的部分作为构造函数的初值
string s(str, strbegin, strlen) //将字符串str中始于strbegin、长度为strlen的部分作为字符串初值
string s(cstr) //以C_string类型cstr作为字符串s的初值
string s(cstr,char_len) //以C_string类型cstr的前char_len个字符串作为字符串s的初值
strings(num, c) //生成一个字符串,包含num个c字符
strings(strs, beg, end) //以区间[beg, end]内的字符作为字符串s的初值
//析构函数
~string() //销毁所有内存,释放内存
//注意,不能使用字符或者整数去初始化字符串。
std::string s('x'); //错误
std::string s("x"); //正确
std::string s(1, 'x'); //正确
(3)C++获取字符串长度详解
String 类型对象包括三种求解字符串长度的函数:size() 和 length()、 maxsize() 和 capacity():
- size() 和 length():这两个函数会返回 string 类型对象中的字符个数,且它们的执行效果相同。
- max_size():max_size() 函数返回 string 类型对象最多包含的字符数。一旦程序使用长度超过 max_size() 的 string 操作,编译器会拋出 length_error 异常。
- capacity():该函数返回在重新分配内存之前,string 类型对象所能包含的最大字符数。
string 类型对象还包括一个 reserve() 函数。调用该函数可以为 string 类型对象重新分配内存。重新分配的大小由其参数决定。reserve() 的默认参数为 0。
(4)string获取字符串元素:[]和at()
字符串中元素的访问是允许的,一般可使用两种方法访问字符串中的单一字符:下标操作符[] 和 成员函数at()。两者均返回指定的下标位置的字符。第 1 个字符索引(下标)为 0,最后的字符索引为 length()-1。
需要注意的是,这两种访问方法是有区别的:
- 下标操作符 [] 在使用时不检查索引的有效性,如果下标超出字符的长度范围,会示导致未定义行为。对于常量字符串,使用下标操作符时,字符串的最后字符(即 '\0')是有效的。对应 string 类型对象(常量型)最后一个字符的下标是有效的,调用返回字符 '\0'。
- 函数 at() 在使用时会检查下标是否有效。如果给定的下标超出字符的长度范围,系统会抛出 out_of_range 异常。
(5)C++ string字符串比较方法详解
Basic_string 类模板既提供了 >、<、==、>=、<=、!= 等比较运算符,还提供了 compare() 函数,其中 compare() 函数支持多参数处理,支持用索引值和长度定位子串进行比较。该函数返回一个整数来表示比较结果。如果相比较的两个子串相同,compare() 函数返回 0,否则返回非零值。
4.容器
容器是用来管理某一类对象的集合,包括序列式容器和关联式容器。
STL 中已经提供的容器主要如下:
- vector <T>:一种向量。
- list <T>:一个双向链表容器,完成了标准 C++ 数据结构中链表的所有功能。
- queue <T>:一种队列容器,完成了标准 C++ 数据结构中队列的所有功能。
- stack <T>:一种栈容器,完成了标准 C++ 数据结构中栈的所有功能。
- deque <T>:双端队列容器,完成了标准 C++ 数据结构中栈的所有功能。
- priority_queue <T>:一种按值排序的队列容器。
- set <T>:一种集合容器。
- multiset <T>:一种允许出现重复元素的集合容器。
- map <key, val>:一种关联数组容器。
- multimap <key, val>:一种允许出现重复 key 值的关联数组容器。
序列式容器:vector,list,deque,queue,stack,priority_queue
关联式容器:map,set
5.序列式容器的种类?
序列容器以线性序列的方式存储元素。它没有对元素进行排序,元素的顺序和存储它们的顺序相同。以下有5种标准的序列容器,每种容器都具有不同的特性:
- array<T,N>(数组容器)是一个长度固定的序列,有 N 个 T 类型的对象,不能增加或删除元素。
- vector<T>(向量容器)是一个长度可变的序列,用来存放 T 类型的对象。必要时,可以自动增加容量,但只能在序列的末尾高效地增加或删除元素。
- deque<T>(双向队列容器)是一个长度可变的、可以自动增长的序列,在序列的两端都不能高效地增加或删除元素。
- list<T>(链表容器)是一个长度可变的、由 T 类型对象组成的序列,它以双向链表的形式组织元素,在这个序列的任何地方都可以高效地增加或删除元素。访问容器中任意元素的速度要比前三种容器慢,这是因为 list<T> 必须从第一个元素或最后一个元素开始访问,需要沿着链表移动,直到到达想要的元素。
- forward list<T>(正向链表容器)是一个长度可变的、由 T 类型对象组成的序列,它以单链表的形式组织元素,是一类比链表容器快、更节省内存的容器,但是它内部的元素只能从第一个元素开始访问。
函数成员 | array<T,N> | vector<T> | deque<T> |
---|---|---|---|
begin() - 返回幵始迭代器 | 是 | 是 | 是 |
end() - 返回结束迭代器 | 是 | 是 | 是 |
rbegin() - 返回反向'开始迭代器 | 是 | 是 | 是 |
rend() - 返回反向结束迭代器 | 是 | 是 | 是 |
cbegin() - 返M const开始迭代器 | 是 | 是 | 是 |
cend() - 返回const结束迭代器 | 是 | 是 | 是 |
crbegin() - 返回const反向开始迭代器 | 是 | 是 | 是 |
crend() - 返回const反向结束迭代器 | 是 | 是 | 是 |
assign() - 用新元素替换原有内容 | - | 是 | 是 |
operator=() - 复制同类型容器的元素,或者用初始化列表替换 现有内容 | 是 | 是 | 是 |
size() - 返回实际元素个数 | 是 | 是 | 是 |
max_size() - 返回元素个数的设大值 | 是 | 是 | 是 |
capacity() - 返回当前容量 | - | 是 | - |
empty() - 返回true,如果容器中没有元素的话 | 是 | 是 | 是 |
resize() - 改变实际元素的个数 | - | 是 | 是 |
shrink _to_fit() - 将内存减少到等于当前元素实际所使用的大小 | - | 是 | 是 |
front() - 返回第一个元素的引用 | 是 | 是 | 是 |
back() - 返回铖后一个元素的引用 | 是 | 是 | 是 |
operator[]() - 使用索弓丨访问元素 | 是 | 是 | 是 |
at() - 使用经过边界检査的索引访问元素 | 是 | 是 | 是 |
push_back() - 在序列的尾部添加一个元素 | - | 是 | 是 |
insert() - 在指定的位置插入一个或多个元素 | - | 是 | 是 |
emplace() - 在指定的位置直接生成一个元素 | - | 是 | 是 |
emplace_back() - 在序列尾部生成一个元素 | - | 是 | 是 |
pop_back() - 移出序列尾部的元素 | - | 是 | 是 |
erase() - 移出一个元素或一段元素 | - | 是 | 是 |
clear() - 移出所苻的元素,容器大小变为 0 | - | 是 | 是 |
swap() - 交换两个容器的所有元素 | 是 | 是 | 是 |
data() - 返回包含元素的内部数组的指针 | 是 | 是 | - |
函数成员 | list<T> | forward list<T> |
---|---|---|
begin() - 返回开始迭代器 | 是 | 是 |
end() - 返回结束迭代器 | 是 | 是 |
rbegin() - 返回反向开始迭代器 | 是 | - |
rend() - 返回反向结束迭代器 | 是 | - |
cbegin() - 返回 const 开始结束迭代器 | 是 | 是 |
before_begin() - 返回一个指向第一个元素前一个位置的迭代器 | - | 是 |
cbefore_begin() - 返回一个指向第一个元素前一个位置的const迭代器 | - | 是 |
cend() - 返回 const 结束迭代器 | 是 | 是 |
crbegin() - 返回 const 反向开始迭代器 | 是 | - |
crend() - 返回 const 反向结束迭代器 | 是 | - |
assign() - 用新元素替换原有内容 | 是 | 是 |
operator=() - 复制同类型容器的元素,或者用初始化列表替换现有内容 | 是 | 是 |
size() - 返回实际元素个数 | 是 | - |
max_size() - 返回元素个数的最大值 | 是 | 是 |
resize() - 改变实际元素的个数 | 是 | 是 |
empty() - 返回 true,如果容器中没有元素的话 | 是 | 是 |
from() - 返回第一个元素的引用 | 是 | 是 |
back() - 返回最后一个元素的引用 | 是 | - |
push_back() - 在序列的潘部添加一个元素 | 是 | - |
push_front() - 在序列的起始位置添加一个元素 | 是 | 是 |
emplace() - 在指矩位置直接生成一个元素 | 是 | - |
emplace_after() - 在指定位置的后面直接生成一个元素 | - | 是 |
emplace_back() - 在序列尾部生成一个元素 | 是 | - |
cmplacc_front() - 在序列的起始位生成一个元索 | 是 | 是 |
insert() - 在指定的位置插入一个或多个元素 | 是 | - |
insert_after() - 在指定位置的后面插入一个或多个元素 | - | 是 |
pop_back() - 移除序列尾部的元素 | 是 | - |
pop_front() - 移除序列头部的元素 | 是 | 是 |
reverse()-反向元素的顺序 | 是 | 是 |
erase() - 移除指定位置的一个元素或一段元素 | 是 | - |
erase_after() - 移除指定位 1;后面的一个元素或一段元素 | - | 是 |
remove() - 移除所苻和参数匹配的元素 | 是 | 是 |
remove_if() - 移除满足一元函数条件的所有元素 | 是 | 是 |
unique() - 移除所有连续重复的元素 | 是 | 是 |
clear() - 移除所有的元素,容器大小变为 0 | 是 | 是 |
swap() - 交换两个容器的所有元素 | 是 | 是 |
sort() - 对元素进行排序 | 是 | 是 |
merge() - 合并两个有序容器 | 是 | 是 |
splice() - 移动指定位置前面的所有元素到另一个同类型的 list 中 | 是 | - |
splice_after() - 移动指定位置后面的所有元素到另一个同类型的 list 中 | - | 是 |
6.常见的容器适配器?
容器适配器是一个封装了序列容器的类模板,它在一般序列容器的基础上提供了一些不同的功能。之所以称作适配器类,是因为它可以通过适配容器现有的接口来提供不同的功能。
这里有 3 种容器适配器:
- stack<T>:是一个封装了 deque<T> 容器的适配器类模板,默认实现的是一个后入先出(Last-In-First-Out,LIFO)的压入栈。stack<T> 模板定义在头文件 stack 中。
- queue<T>:是一个封装了 deque<T> 容器的适配器类模板,默认实现的是一个先入先出(First-In-First-Out,LIFO)的队列。可以为它指定一个符合确定条件的基础容器。queue<T> 模板定义在头文件 queue 中。
- priority_queue<T>:是一个封装了 vector<T> 容器的适配器类模板,默认实现的是一个会对元素排序,从而保证最大元素总在队列最前面的队列。priority_queue<T> 模板定义在头文件 queue 中。
7.stack堆栈操作
stack<T>容器适配器中的数据是以 LIFO 的方式组织的,和其他序列容器相比,stack 是一类存储机制简单、所提供操作较少的容器。下面是 stack 容器可以提供的一套完整操作:
top():返回一个栈顶元素的引用,类型为 T&。如果栈为空,返回值未定义。
push(const T& obj):可以将对象副本压入栈顶。这是通过调用底层容器的 push_back() 函数完成的。
push(T&& obj):以移动对象的方式将对象压入栈顶。这是通过调用底层容器的有右值引用参数的 push_back() 函数完成的。
pop():弹出栈顶元素。
size():返回栈中元素的个数。
empty():在栈中没有元素的情况下返回 true。
emplace():用传入的参数调用构造函数,在栈顶生成对象。
swap(stack<T> & other_stack):将当前栈中的元素和参数中的元素交换。参数所包含元素的类型必须和当前栈的相同。对于 stack 对象有一个特例化的全局函数 swap() 可以使用。
8. queue(STL queue)用法
只能访问 queue<T> 容器适配器的第一个和最后一个元素。只能在容器的末尾添加新元素,只能从头部移除元素。
queue操作:
queue 和 stack 有一些成员函数相似,但在一些情况下,工作方式有些不同:
(1)front():返回 queue 中第一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。
(2)back():返回 queue 中最后一个元素的引用。如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。
(3)push(const T& obj):在 queue 的尾部添加一个元素的副本。这是通过调用底层容器的成员函数 push_back() 来完成的。
(4)push(T&& obj):以移动的方式在 queue 的尾部添加元素。这是通过调用底层容器的具有右值引用参数的成员函数 push_back() 来完成的。
(5)pop():删除 queue 中的第一个元素。
(6)size():返回 queue 中元素的个数。
(7)empty():如果 queue 中没有元素的话,返回 true。
(8)emplace():用传给 emplace() 的参数调用 T 的构造函数,在 queue 的尾部生成对象。
(9)swap(queue<T> &other_q):将当前 queue 中的元素和参数 queue 中的元素交换。它们需要包含相同类型的元素。也可以调用全局函数模板 swap() 来完成同样的操作。
9.C++序列容器存储智能指针
通常用容器保存指针比保存对象更好,而且大多数时候,保存智能指针比原生指针好。下面是一些原因:
在容器中保存指针需要复制指针而不是它所指向的对象。复制指针通常比复制对象快。
(1)在容器中保存指针可以得到多态性。存放元素基类指针的容器也可以保存其派生类型的指针。当要处理有共同基类的任意对象序列时,这种功能是非常有用的。应用这一特性的一个常见示例是展示一个含有直线、曲线和几何形状的对象序列。
(2)对指针容器的内容进行排序的速度要比对对象排序快;因为只需要移动指针,不需要移动对象。
(3)保存智能指针要比保存原生指针安全,因为在对象不再被引用时,自由存储区的对象会被自动删除。这样就不会产生内存泄漏。不指向任何对象的指针默认为 nullptr。
10.各容器的实现原理
vector 拥有一段连续的内存空间
list 就是数据结构中的双向链表
deque 的动态数组首尾都开放
set 有序的容器,红黑树的平衡二叉检索树的数据结构
multiset 红黑树实现的,set插入的元素不能相同,但是multiset可以相同。
map 键不能重复,红黑树实现的,
mtltimap 红黑树实现的,允许键有重复
这一章感觉做成了字典,不应该这样的!所以不再添加内容!这部分主要是各个容器的操作函数和算法函数较多,感觉用的时候查一查。提供学习的地址:http://c.biancheng.net/stl/algorithms/