https://gitee.com/quicksands/stl-source-code-analysis
C++11关键字:auto和decltype
- auto:占位符类型说明符
- 对于变量,
auto x = expr;从初始化器推导类型
- 对于变量,
- decltype说明符
decltype (expr)声明从表达式得到的类型
容器
- 容器是储存其他对象的对象。简单来说,每个容器提供了一种适配大部分类型的数据结构。
- 容器分为四种:
- 序列式容器:
<array><deque><forward_list><list><vector> - 关联式容器:
<map><set> - 无序关联式容器:
<unordered_map><unordered_set> - 容器适配器:
<queue><stack>
- 序列式容器:
序列式容器
| 顺序容器 | 顺序容器实现能按顺序访问的数据结构 |
|---|---|
| array(c++11) | 静态(固定长度) 的连续数组 (类模板)![]() |
| vector | 动态的连续数组 (类模板)Implementation |
| deque | 双端队列 (类模板)Implementation |
| forard_list(c++11) | 单链表 (类模板) |
| list | 双链表 (类模板)Implementation |









eg
- vector
vector<T>是动态的连续数组。- 动态指它的长度是可变的;连续指它的元素可用T*访问。
- 它实现了两种元素访问
- operator [],注意:不检查下标是否越界
- 访问元素函数(返回元素的左值):front,at(int),back。其中,at检查下标越界,越界则抛出异常。
- 实现了列表初始化(直接列表和复制列表)
- 使用迭代器
- 迭代器(Iterator)是用于遍历容器元素的指针对象的包装。
- 单向迭代器实现了以下运算符重载
- operator ++,==, != , * 等,例如:++ 表示取容器中的下一个元素
- 容器会提供一个或多个迭代器实现。
- 例如:
- vector提供正向和反向的迭代器。
- 通过成员函数begin(),end()返回正向迭代器对象实例。
- 通过成员函数rbegin(),rend()返回反向迭代器对象实例。


- 例如:
关联式容器

| 类名 | 说明 | 所在头文件 |
|---|---|---|
| map | 通过键进行元素存取的关联数组 | <map> |
| multimap | 支持重复键的关联数组 | <map> |
| set | 任何元素的集合 | <set> |
| multiset | 可以重复的集合 | <set> |
| unordered_map | 无序的map,类似于哈希表 | <unordered_map> |
| unordered_set | 无序的set,类似于哈希表 | <unordered_set> |
- std::pair
- std::map的某些函数使用了中的类std::pair,pair<T1, T2>代表一个由类型T1和类型T2组成的有序对。
- 可以直接用构造函数
std::pair<T1, T2> (v1, v2)进行构造,也可以用make_pair进行构造:auto p = make_pair<v1,v2>; - 通过
p.first访问第一个元素,通过p.second访问第二个元素
map




multimap


set

适配器


stack



queue

priority_queue

迭代器
- 迭代器是每种容器各自定义的一个或多个不同于容器的类,比如
vector<T>::iterator,它主要用于访问、修改、增加、删除容器中的元素。 - 按照功能的不同,C++17之前的迭代器分为:
- LegacyInputIterator(输入迭代器)
- LegacyOutputIterator(输出迭代器)
- LegacyForwardIterator(单向迭代器)
- LegacyBidirectionalIterator(双向迭代器)
- LegacyRandomAccessIterator(随机迭代器)
- C++17加入了LegacyContiguousIterator(连续迭代器)






- 失效案例分析
vector<int> ivv1 {1,2,4,5,3};
for (auto it = ivv1.begin(); it != ivv1.end(); it++) {
if (*it == 3) ivv1.erase(it);
}
-
在 for 循环中,当你调用 ivv1.erase(it) 删除元素 3 后,当前迭代器 it 就失效了(即不再指向合法位置);
-
但是 for 循环的条件中仍然执行了 it++,这导致你对一个已经失效的迭代器自增,这属于未定义行为(UB);
-
结果可能是程序崩溃、输出错误结果,或“看起来没错但风险极高”。
修正代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> ivv1 {1,2,3,4,5};
for (auto it = ivv1.begin(); it != ivv1.end(); ) {
if (*it == 3)
it = ivv1.erase(it); // 返回新的有效迭代器
else
++it;
}
for (auto x : ivv1) cout << x << ",";
cout << endl;
}
算法




#include<iostream>
#include<functional>
using namespace std;
int twox_add_threey(int x,int y){
return 2*x+3*y;
}
class Foos{
public:
static int twox_add_threey(int x,int y){
return 2*x+3*y;
}
};
class Food{
public:
int twox_add_threey(int x,int y){
return 2*x+3*y;
}
};
class Func{
private:
int a,b;
public:
Func(int _a=0,int _b=0):a(_a),b(_b){}
int operator()(int x,int y){
return a*x+b*y;
}
};
void callback_client(std::function<int(int,int)> f,int a,int b){
cout<<f(a,b)<<endl;
}
int main(){
cout<<"普通函数回调:";
callback_client(twox_add_threey,1,2);
cout<<"类的静态成员函数回调:";
callback_client(Foos::twox_add_threey,1,2);
cout<<"类的动态成员函数回调:";//动态成员函数需要对象才能调用
Food food;
callback_client(std::bind(&Food::twox_add_threey,&food,std::placeholders::_1,std::placeholders::_2),1,2);
callback_client(std::bind(food.twox_add_threey,&food,std::placeholders::_1,std::placeholders::_2),1,2);
callback_client([&food](int x,int y){return food.twox_add_threey(x,y);},1,2);
cout<<"函数对象回调:";callback_client(Func(2,3),1,2);
cout<<"匿名函数回调:";callback_client([](int x,int y){return 2*x+3*y;},1,2);
return 0;
}





525

被折叠的 条评论
为什么被折叠?



