[笔记]c++基础实践《三》STL详解

C++ C++实战笔记


前言

STL(Standard Template Library)标准模板库

STL大致分为六大模块:容器(container),算法(algorithm),迭代器(iterator),仿函数(functor),配接器(adapter),配置器(allocator)

一、容器

container
C++ STL顺序容器详解(一)

你必须要知道所有容器都具有的一个基本特性:
它保存元素采用的是“值”(value)语义,也就是说,容器里存储的是元素的拷贝、副本,而不是引用。

容器操作元素的很大一块成本就是值的拷贝。所以,如果元素比较大,或者非常多,那么操作时的拷贝开销就会很高,性能也就不会太好。

  • 尽量为元素实现转移构造和转移赋值函数,在加入容器的时候使用std::move()来“转移”,减少元素复制的成本:
Point p;                        // 一个拷贝成本很高的对象
v.push_back(p);                // 存储对象,拷贝构造,成本很高
v.push_back(std::move(p));    // 定义转移构造后就可以转移存储,降低成本

// 直接使用C++11为容器新增加的emplace操作函数,它可以“就地”构造元素,免去了构造后再拷贝、转移的成本
v.emplace_back(...);            // 直接在容器里构造元素,不需要拷贝或者转移
  • 容器中存放指针,则必须要自己手动管理元素的生命周期
    如果真的有这种需求,可以考虑使用智能指针unique_ptr/shared_ptr,让它们帮你自动管理元素。

1.1 顺序容器

1.1.1 std::vector

初始化

方法一

vector<int> vi; 

方法二

vector<int> vi(10,10);//size 10,each value 10

方法三

vector<int> vi(arr,arr+10);//begin,end
插入

方法一 push_back、emplace_back、emplace

vector<T> a;
T val;
a.push_back( val);//在末尾插入一个元素

方法二 insert

v2.insert(v2.begin()+4, L"3");   //在指定位置,例如在第五个元素前插入一个元素

v2.insert(v2.end(), L"3");   //在末尾插入一个元素

v2.insert(v2.begin(), L"3");   //在开头插入一个元素
查找

方法一 迭代器

    #include <algorithm>

	...
    vector<int> vec;
    ...
    vector<int>::iterator it = find(vec.begin(), vec.end(), value);
 
    if (it != vec.end()){
		//找到了
    }

方法二 数组查找

std::vector <T> a;
for (size_t i = 0; i < a.size(); i++)
{
	if(value ==  a[i];{
	//找到了
	}
}
遍历

方法一 迭代器

std::vector <T> a;

std::vector <T>::iterator iVector = a.begin();  

while(iVector != a.end())
{
 std::cout<<" dump "<< (*iVector)<<std::endl;
 ++iVector;  
}  

方法二 数组

std::vector <T> v1;
for (size_t i = 0; i < v1.size(); i++)
{
	T tempNum = v1[i];
}
删除
删除最后一个元素
   v1.pop_back();   //删除最后一个元素
删除开头的元素
   v1.erase(v2.begin()); //删除开头的元素
删除[begin,end]区间的元素
   v1.erase(v1.begin(),v1.end); 

或者删除范围内的

	v1.erase(v1.begin(),v1.begin() + n); 
删除全部元素

方法一

v1.clear()

方法二

std::vector<T>::iterator iVector = v1.begin();

while(iVector != v1.end())
{
delete (*iVector)->p;
iVector = v1.erase(iVector);
}

方法三

while(pVector->size() != 0)
{
//pop_back方法无返回值
pVector->pop_back();
//删除操作避免大量移动的方法,如果元素有申请堆栈的内存,不可用此方法
}
push_back 与 emplace_back区别

push_back拷贝数据结构,所以有两次构造调用
emplace_back直接调用构造函数,只有1次构造调用

emplace_back, emplace_font与emplace区别

emplace_back:尾插
emplace_font:头插
emplace:容器指定位置之前插入一个新的元素

1.2 线性容器

1.1.3 std::list

初始化
list<int> li(10);
list<int> li2(10);

list<int> li3(10,1);//size 10,each value 1

int arr2[10] = {};
list<int> li4(arr2,arr2+10);//begin,end

1.3 关联容器

关联容器底层数据结构:unordered_map/set基于hash表,不保证插入顺序;map/set基于红黑树,根据键自动排序

1.3.1 std::map

插入

方法一 数组

//map[key] = value
map<int,string> mis; 
mis[0] = "first"; 
mis[1] = "second"; 
mis[2] = "third"; 

方法二 pair

//make_pair
map<int,string> mis2(mis.begin(),mis.end());
mis.insert(pair<int, string>(3, "fourth"));

方法三 make_pair

mapStudent.insert(make_pair(1, "student_one")); 

方法四 value_type

//value_type
mis.insert(map<int, string>::value_type(3, "fourth")); 

for (auto& pair : mis){ 
	cout << pair.first << ":" << pair.second.c_str() << endl;
}
查找

方法一

std::map<T,V> m1;
T key;
...
if(m1.find(key) != m1.end){
//找到了
}
删除
删除所有

方法一

cmap.erase(cmap.begin(), cmap.end());

方法二

cmap.clear()
删除范围

例如删除map前5个

auto first = map_data.begin();
map_data.erase(first, std::next(first, 5));
排序删除
/* Online C++ Compiler and Editor */
#include <iostream>
#include <string>
#include <map>

using namespace std;

int main()
{
   

std::map<std::string,int> map_data;

map_data["1"] = 1;
map_data["2"] = 1;
map_data["3"] = 1;
map_data["4"] = 1;
map_data["5"] = 1;
map_data["6"] = 1;
map_data["7"] = 1;
map_data["8"] = 1;
map_data["9"] = 1;
map_data["10"] = 1;
for(auto item:map_data){
    printf("map_data[%s]=%d\n", item.first.c_str(), item.second);
}

std::vector<std::pair<std::string, ConnectCacheInfo>> vec(map_data.begin(),
                    map_data.end());
                sort(vec.begin(),
                    vec.end(),
                    [=] (std::pair<std::string, int> p1, std::pair<std::string, int> p2)
                    {
                        return atoi(p1.first) > atoi(atoi(p2.first);
                    }
                );

map_data.clear();
                for (int i = 0; i < vec.size(); ++i) {
                    map_data.emplace(vec[i]);
                }



if (map_data.size() > 10) {
   auto first = map_data.begin();
   map_data.erase(first, std::next(first, 5));
}

for(auto item:map_data){
    printf("map_data[%s]=%d\n", item.first.c_str(), item.second);
}

   
   return 0;
}

1.3.2 std::unordered_map

无序的map

不排序的unordered_map怎么做到快速查找?靠的就是unordered_map的第三个模板参数,把哈希算法传递进去。储存数据的时候会顺便算一遍 Key 的哈希值并保存起来,需要查找的时候就用哈希值来找。

默认情况下,unordered_map已经预先设定好使用std::hash作为第三个模板参数。如果不想使用std::hash,而是想用自己的,那就

std::unordered_map<int, std::string, MyHash> test_map;

其中MyHash是自己实现的Hash算法类。

1.3.3 std::multimap

多重映射是允许一个键对应多个附加数据的映射。

1.3.4 std::set

1.3.5 std::multiset

多重集合是允许有重复元素的集合

二、算法

algorithm
算法库
C++STL库之algorithm库

三、迭代器

iterator

cpp 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型

四、仿函数

functor

仿函数(Functor)又称为函数对象(Function Object)是一个能行使函数功能的类。仿函数的语法几乎和我们普通的函数调用一样,不过作为仿函数的类,都必须重载 operator() 运算符。因为调用仿函数,实际上就是通过类对象调用重载后的 operator() 运算符。

五、适配器

adapter

是把一个事物,改造一下接口等等。使得其看起来像一个新的事物。适配器其实是一种应用在STL的设计模式。

六、配置器

allocator

默默完成内存配置与释放,对象构造和析构的工作。

空间配置器

总结

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二进制怪兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值