C++ STL学习笔记(3) 分配器Allocator,OOP, GP简单介绍

5 篇文章 4 订阅

         继续学习侯捷老师的课程!

         在前面的博客《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
{
	...
};

--------------------------------------------------------分割线------------------------------------------------------------

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11STL中常用的迭代器算法有以下几个,分别是: 1. copy:将一个序列复制到另一个序列中。 2. reverse:将一个序列翻转。 3. sort:对一个序列进行排序。 4. unique:去除一个序列中的重复元素。 下面对每个算法进行详细介绍: 1. copy copy函数用于将一个序列复制到另一个序列中。其函数原型如下: ```c++ template <class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); ``` 其中,first和last分别表示被复制序列的起始位置和结束位置(注意,end位置并不包括在序列内),result表示将要复制到的序列的起始位置。 例如,如果有两个整数数组a和b,我们想要将a中的元素复制到b中,可以这样写: ```c++ int a[] = {1, 2, 3, 4, 5}; int b[5]; copy(a, a + 5, b); ``` 这里,a和a+5分别表示数组a的起始位置和结束位置,b表示数组b的起始位置。复制后,数组b的内容为:{1, 2, 3, 4, 5}。 2. reverse reverse函数用于将一个序列翻转。其函数原型如下: ```c++ template <class BidirectionalIterator> void reverse(BidirectionalIterator first, BidirectionalIterator last); ``` 其中,first和last分别表示序列的起始位置和结束位置(注意,end位置并不包括在序列内)。 例如,如果有一个整数数组a,我们想要将其翻转,可以这样写: ```c++ int a[] = {1, 2, 3, 4, 5}; reverse(a, a + 5); ``` 这里,a和a+5分别表示数组的起始位置和结束位置。翻转后,数组a的内容为:{5, 4, 3, 2, 1}。 3. sort sort函数用于对一个序列进行排序。其函数原型如下: ```c++ template <class RandomAccessIterator> void sort(RandomAccessIterator first, RandomAccessIterator last); ``` 其中,first和last分别表示序列的起始位置和结束位置(注意,end位置并不包括在序列内)。该函数只能用于随机访问迭代器。 例如,如果有一个整数数组a,我们想要将其排序,可以这样写: ```c++ int a[] = {5, 3, 1, 4, 2}; sort(a, a + 5); ``` 这里,a和a+5分别表示数组的起始位置和结束位置。排序后,数组a的内容为:{1, 2, 3, 4, 5}。 4. unique unique函数用于去除一个序列中的重复元素。其函数原型如下: ```c++ template <class ForwardIterator> ForwardIterator unique(ForwardIterator first, ForwardIterator last); ``` 其中,first和last分别表示序列的起始位置和结束位置(注意,end位置并不包括在序列内)。该函数只能用于前向迭代器。 例如,如果有一个整数数组a,其中有重复元素,我们想要去除重复元素,可以这样写: ```c++ int a[] = {1, 2, 2, 3, 3, 3, 4, 5, 5}; int* p = unique(a, a + 9); ``` 这里,a和a+9分别表示数组的起始位置和结束位置。去重后,数组a的前p-a个元素是不重复的,p之后的元素是无用的。这里,p指向的位置是a+5,即数组a的前5个元素是不重复的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值