一、STL 1
二、string字符串 3
三、vector 5
一、STL
1.STL简介
STL的代码分三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模板函数的方式。在C++标准中,STL被组织为13个头文件:
<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>、<utility>
2.STL的组件(6部分):容器、迭代器、算法、仿函数、内存配置器、配接器。
迭代器的分类:双向迭代器、随机存取迭代器
STL中的算法:搜索、排序、复制、修改、数值运算。
STL中大量使用仿函数,仿函数具有泛型编程强大威力和纯粹抽象概念的特征!
图1STL结构图
1. 容器
STL容器分为两大类:序列式容器(vector、list、deque)、关联式容器(set、map、multiset、multimap)
名称 | 说明 |
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值的关联数组容器 |
1. STL算法
STL中的所有算法都是基于模板实现的。这些算法都定义在标准名空间std内。通过包含<algorithm>来获得使用权。
部分常见算法:
for_each() |
find() |
find_if() |
count() |
count_if() |
replace() |
replace_if() |
copy() |
unique_copy() |
sort() |
equal_range() |
merge() |
3. 迭代器
迭代器就是指示器。迭代器为访问容器内的元素提供了通用的方法,类似于C++的指针。
当参数化类型是C++的内部类型时,迭代器即C++指针。
STL定义了5种类型的迭代器,每种容器都支持某种类别的迭代器。
常见的迭代器类别包括:输入、输出、前向、双向、和随机访问
4. 仿函数
C++中,函数调用一般使用指针(函数地址),当需要调用函数时,只需告诉函数的地址即可。
static int cmp(int* i, int* j){ return (*i - *j); }
当需要调用上面定义的函数时,只需要提供函数的地址即可:
qsort(1, 10, sizeof(int), cmp);
这种方法的缺点就是效率低,为了提高效率,STL定义了仿函数的概念。
定义仿函数,其特征就是使用operator()来定义,
struct three_mul
{
bool operator()(int& v)
{
return (v % 3 == 0);
}
};
通过运算符定义能显著提高效率。
for_each(muvector.begin(), myvector.end(), three_mul);
5. 内存配置器
STL包括底层的内存分配和释放。allocator
配接器可以实现不同类之间的数据转换。最常用的配接器有istream_iterator:提供了函数copy的接口。
adapter对于STL来说非常重要。
STL提供了3中容器配接器:stack<Container>、queue<Container>、deque<Container>
二、string字符串
在STL库中,basic_string有两个预定义类型:包含char的string类型和包含wchar的wstring类型!
typedef basic_string<char, char_traits<char>, allocator<char> >
string;
typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >
wstring;
字符串库简介、字符的特点、字符串类(basic_string)、字符串通用函数、字符串连接、字符串I/O、搜索和查找、字符串迭代器、字符串配置器。
配置器的作用就是为容器开辟内存!
配置器最早是为了将内存模型抽象化而提出来的。所有内存配置器分配内存是按对象的个数而不是按字节数来分配的,区别于new和new[]操作符。
配置器实现了将算法、容器、与物理存储细节相隔离。
配置器提供了一套分配与释放内存的标准方式,并提供用作指针类型和引用类型的标准名字。
配置器是一种纯粹的抽象,只要行为上像分配器的类型都可以看作是配置器。
C++ STL提供了标准分配器。
basic_string模板以及string类均提供了对常见配置器的相关支持。
class Allocator=allocator<char>
2.string类方法汇总:
函数名 | 功能 |
构造函数 | 生成或复制字符串 |
析构函数 | 销毁字符串 |
赋值=,assign | 赋予新值 |
swap | 交换两字符串对象的内容 |
+=,append(),push_back() | 在尾部追加字符串 |
empty() | 判断字符串是否为空 |
capacity() | 返回字符容量 |
reserve() | 预留内存以存储一定数量的字符 |
[]、at() | 下标访问一个字符 |
>>、getline() | 从stream中读取字符串 |
<< | 将字符串值写入流对象 |
insert() | 插入字符、字符串 |
erase() | 删除字符 |
clear() | 删除全部字符 |
resize() | 改变字符数量 |
replace() | 替换字符 |
+ | 串联字符串 |
==、!=、<、<=、>、>=、compare() | 按字典顺序比较字符串值大小 |
size()、length() | 返回字符数量 |
max_size() | 返回一个string对象能存的最大字符个数 |
copy() | 将内容复制为一个C-string |
c_str() | 返回C风格C-string字符串 |
data() | 将内容以字符数组形式返回 |
substr() | 返回子字符串 |
find() | 搜寻某个字符或子串 |
begin()、end() | 正向迭代器 |
rbegin()、rend() | 提供逆向迭代器 |
get_allocator() | 返回配置器 |
三、vecto
参考资料:http://www.cplusplus.com/reference/vector/vector/?kw=vector
1. 序列式容器vector类模板
- vector对象的定义;
- vector对象的初始化(默认无参构造函数、带参构造函数、指针迭代器区间、复制构造);
- vector容器的大小(size)和容量(capacity)
- vector类的成员函数:
- 是否为空:empty() //size=0
- 遍历vector:vector<T>::iterator和at()函数
- 元素访问方法:at()、[]、front()、back()
- 使用算法:for_each()函数、count()函数、count_if()函数[仿函factor]
- 插入元素:push_back()插到末尾、使用insert()函数将元素对象插入到vector任意位置。
- 删除元素:pop_back()、erase()、clear();[算法库的remove()]
- 交换对象swap():用于两个vector型容器(二者类型最好相同)之间元素互换。
- 元素查找和搜索:STL的通用算法:find()、find_if()
- 元素排序:使用STL的通用算法sort()、qsort()。vector类没有提供排序的成员函数。
- vector<bool>:专门用于bool型,位运算等。
支持随机访问,vector迭代器是随机存取迭代器,适用于任何STL算法
相当于动态数组
在末端插入或删除元素:vector性能相当好!
vector可以实现数据结构中的队列、数组、堆栈的所有功能
// TEMPLATE CLASS vector
template<class _Ty,
class _Alloc = allocator<_Ty> >
class vector
: public _Vector_alloc<!is_empty<_Alloc>::value,
_Vec_base_types<_Ty, _Alloc> >
{ // varying size array of values
...
}
vector中的元素可以是任意类型 T(只要具备可设置setValue和可复制=两个属性)
第二个模板参数是关于空间配置器设置的,用于定义内存模型,默认内存模型是C++标准库提供的allocator.
参考:https://blog.csdn.net/linwh8/article/details/51386430
vector类介绍
According to cplusplus.com,
Vectors are sequencecontainers representing arrays that can change in size.(序列容器)
Just like arrays, vectorsuse contiguous storage locations for their elements, which means thattheir elements can also be accessed using offsets on regular pointers to itselements, and just as efficiently as in arrays.* But unlike arrays, their sizecan change dynamically, with their storage being handled automatically by thecontainer*.
Internally, vectors use a dynamically allocated array to store their elements.This array may need to be reallocated in order to grow in size when newelements are inserted, which implies allocating a new array and moving allelements to it. This is a relatively expensive task in terms of processingtime, and thus, vectors do not reallocate each time an element is added to thecontainer.
Instead, vectorcontainers may allocate some extra storage to accommodate for possible growth,and thus the container may have an actual capacity greater than the storagestrictly needed to contain its elements (i.e., its size). Libraries can implement different strategiesfor growth to balance between memory usage and reallocations, but in anycase, reallocations should only happen at logarithmically growing intervals ofsize so that the insertion of individual elements at the end of the vector canbe provided with amortised constant time complexity (see push_back).
Therefore, compared to arrays, vectorsconsume more memory in exchange for the ability to manage storage and growdynamically in an efficient way.
Compared to the other dynamic sequencecontainers (deques, lists and forward_lists), vectors are very efficientaccessing its elements (just like arrays) andrelatively efficient adding or removing elements from its end. For operationsthat involve inserting or removing elements at positions other than the end,they perform worse than the others, and have less consistent iterators andreferences than lists and forward_lists.(如果要像数组那样,在任意位置存取,应该用array数组
array<int, 100> myArray; // #include<array>
分析:
(1)vector是array的升级版
vector是一个sequence容器,是array的升级版,主要因为vector能高效地对内存进行管理以及动态增长。但是,vector其实就是将array和方法封装形成的一个类。
(2)vector容器的内存管理
vector的容器大小可以动态增长,但是并不意味着每一次插入操作都进行reallocate。内存的分配与释放耗费的资源是比较大的,因此应当减少它的次数。与此同时,这也就意味着容器的容量(capacity)与容器目前容纳的大小(size)是不等的,前者应大于后者。
补充:上文也说了,对于vector内存的增长有很多strategies,例如第一次增长我增加2个内存单位,第二次增长我增加4个内存单位,第三次,第四次,… 第n次我增长2^n(前提是vector内存不够时再分配),这样也就大大减少了reallocate的次数。
(3)vector容器的意义
然后,vector虽然相对于array消耗了更多的内存,但是却实现了对内存的高效管理和增长,这种消耗是值得的。
(4)vector容器与其他容器的比较
与其他的sequence容器比较(如list,dequeue),vector访问元素的效率较高,但是对于增加与删除操作就不如其他两个容器了。
补充:
(5)vector的容纳对象
vector能容纳绝大多数类型的对象作为它的元素,但是因为引用不是对象,所以不存在包含引用的vector,即引用不能作为vector的对象。并且,vectot容纳的对象也可以是vector,但是有一点要注意,便是在这种情况下vector容器定义的格式:
// 早期c++标准
vector<vector<int> > // 倒数两个尖括号之间要加空格
// c++11
vector<vector<int>> // 倒数两个尖括号之间无需加空格
几种容器操作的时间复杂度:
container | access | insert or erase |
vector | O(1) | O(n^2) |
list | O(n) | O(n) |
dequeue | O(n) | O(n) |
1. vector的几种初始化及赋值方式:
(1) 不带参数的构造函数初始化:
//初始化一个size为0的vector
vector<int> abc;
(1) vector非调用构造函数的初始化;
vector<int> Vector = {1, 2, 3, 4, 5};
// or
vector<int> Vector{1, 2, 3, 4, 5};
// compare
vector<int> Vector(10);
vector<int> Vector(10, 5);
我们可以这样理解:如果vector对象后带的是圆括号,则调用vector的构造函数;如果是花括号,优先考虑列表初始化。如果发现类型不匹配,无法构成列表初始化,则再考虑调用构造函数。
vector<string> Vector{10};
vector<string> Vecytor{10, "hi"};
此时,由于类型不匹配,调用vector构造函数。
(2) 带参数的构造函数初始化
//初始化size,但每个元素值为默认值
vector<int> abc(10); //初始化了10个默认值为0的元素
//初始化size,并且设置初始值
vector<int> cde(10,1); //初始化了10个值为1的元素
(3) 通过数组地址初始化(相当于迭代器区间初始化)
int a[5] = {1,2,3,4,5};
//通过数组a的地址初始化,注意地址是从0到5(左闭右开区间)
vector<int> b(a, a+5);
(4) 通过同类型的vector初始化
vector<int> a(5,1);
//通过a初始化
vector<int> b(a);
2. vector类常用操作:
操作 | 作用 |
(constructor) | Construct vector |
(destructor) | Vector destructor |
operator= | Assign content |
begin | Return iterator to beginning |
end | Return iterator to end |
rbegin | Return reverse iterator to reverse beginning |
rend | Return reverse iterator to reverse end |
cbegin (c++11) | Return const_iterator to beginning |
cend (c++11) | Return const_iterator to end |
crbegin (c++11) | Return const_reverse_iterator to reverse beginning |
crend (c++11) | Return const_reverse_iterator to reverse end |
size | Return size |
max_size | Return maximum size |
resize | Change size |
capacity | Return size of allocated storage capacity |
empty | Test whether vector is empty |
reserve | Request a change in capacity |
shrink_to_fit (c++11) | Shrink to fit |
operator[] | Access element |
at | Access element |
front | Access first element |
back | Access last element |
data (c++11) | Access data |
assign | Assign vector content |
push_back | Add element at the end |
pop_back | Delete last element |
insert | Insert elements |
erase | Erase elements |
swap | Swap content |
clear | Clear content |
emplace (c++11) | Construct and insert element |
emplace_back (c++11) | Construct and insert element at the end |
get_allocator | Get allocator |