C++ STL学习笔记(3) 分配器Allocator,OOP, GP简单介绍
继续学习侯捷老师的课程!
在前面的博客《C++ STL学习笔记(2) 容器结构与分类》中介绍了STL中常用到的容器以及他们的使用方法,在我们使用容器的时候,背后需要一个东西支持对内存的使用,这个东西就是分配器(Allocator)。容器一般都会有一个默认的分配器。
例如,以vector为例,可以看到它的定义:
他有一个默认的分配器std::allocator(位于#include <memory>),还有其他的分配器如下所示:
可以定义具有不同分配器的容器:
一般我们不会直接去使用分配器,而是选择使用容器,对于少量的额内存需求,我们会使用new,delete或者malloc, free来分配内存。
-----------------------------------------------------分割线-------------------------------------------------------------------------
OOP与GP的差别:
1. OOP企图将datas和methods关联在一起,类中定义了数据和方法,如下所示:
2. 而GP是将datas和methods分开。例如:
而迭代器相当于容器和算法之间的一个桥梁,算法通过迭代器,对容器中的数据进行特定的操作。
采用泛型编程(GP),Containers和Algorithm团队可以各自“闭门造车”,他们之间只需要以Iterator沟通即可。algorithm通过Iterator确定操作范围,并通过iterator获取容器中的元素。
例如,c++中的max()函数:
template<typename T> T max(const T& a, const T& b) { return (a > b) ? a : b; }
算法团队只需要关注如何实现max()函数,至于a.b之间大小如何比较,则由container团队根据具体的对象实现。
链表list和vector的迭代器的区别:
list的迭代器不是连续的。而vector中的迭代器是连续的,所以可以对vector的迭代器进行+n的操作。所以vector可以使用全局的sort()函数进行排序,而list只能使用list类里面定义的sort方法进行排序。
C++中的另一个概念,特化
C++的模板函数,模板类允许我们定义的类或者函数的参数具有泛化的特性,与之相对,C++也允许我们定义特化的版本。
例如,定义一个泛化的结构体(这个例子是侯捷老师PPT上面的),也是标准库中的源代码
可以定义它的两个特化的版本:
1. 特化版本,当参数的类型是int的时候
2. 特化版本,当参数的类型是doublet的时候
对于上面的泛化特化的概念,可以举一个例子:
// ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include <iostream> template<typename T> // 定义泛化的测试函数 void print_info(T x) { std::cout << "This is a generic version: " << x << std::endl; } template<> // 定义特化的版本 void print_info<int>(int x) { std::cout << "This is a specialization int version: " << x << std::endl; } template<> // 因为已经指定类型,所以不需要在template中声明类型 // 定义特化的版本 void print_info<double>(double x) { std::cout << "This is a specialization double version: " << x << std::endl; } int main() { print_info(5); print_info(5.9); print_info("delf"); print_info('f'); return 0; }
特化可以分为全特化(full specialization) 和 偏特化,也称局部特化(partial specialization),同时,特化又可以分为两种情况
1. 参数个数的特化
例如: 定义一个泛化的类:
template<typename T, typename Alloc = alloc> // 泛化的类 class vector { ... };
再定义一个偏特化的类:
template<typename Alloc> // 特化的版本 class vector<bool, Alloc> // 这里只对第一个类型进行特化,第二个类型还是泛化,所以称为偏特化 { ... };
2.参数范围的特化,这里的范围指的是类型的范围
具体的意思如下面的程序所示:
1. 定义一个泛化的版本:
template<typename Iterator> struct iterator_traits { ... };
2. 定义一个特化的版本:
template<typename Iterator> struct iterator_traits { ... };
--------------------------------------------------------分割线------------------------------------------------------------
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)