分配器
一:分配器概述:和容器紧密关联,一起使用
每次malloc(),都浪费大量内存。
确切的说:内存分配器,扮演内存池的角色,通过大量减少对malloc()的调用,来节省内存,甚至还有一定的分配效率的提高;
经过测试,allocator这个c++标准库提供的缺省的内存分配器压根就没有采用内存池的工作机制。估计底层原封不动的调用了 malloc();
namespace _nmsp1
{
void func()
{
//list<int> mylist;
//list<int, std::allocator<int> > mylist;
//typename = _Alloc = allocator<....> 一个分配器
list<int> mylist; //双向链表,内存不要求挨着;
mylist.push_back(10);
mylist.push_back(20);
mylist.push_back(36);
for (auto iter = mylist.begin(); iter != mylist.end(); ++iter)
{
cout << *iter << endl;
int *p = &(*iter);
printf("%p\n", p);
}
mylist.pop_back(); //干掉36
//int *psuibian = new int(100);
return;
}
}
namespace _nmsp2
{
//二:分配器的使用
//allocator分配器,是个类模板,我们写代码时极少会直接用到这个allocator这种容器的分配器;
//但从语法上来讲,allocator分配器是能够被直接编码使用的
void func()
{
//list<int,
allocator<int> aalloc; //定义一个aalloc对象,为类型为int的对象分配内存
int *p = aalloc.allocate(3); //allocate()是分配器中的重要函数,用来分配一段原始的未构造的内存。
//这段内存能保存3个类型为int的对象(12字节);
int *q = p;
*q = 1; q++;
*q = 2; q++;
*q = 3;
aalloc.deallocate(p, 3); //deallocate()也是分配器中的重要函数,用于释放内存,你需要记住分配了几个对象,释放时要释放正确数量的对象;
}
}
namespace _nmsp3
{
//三:其他的分配器及原理说
//linux GNU c++(gcc,g++)
//四:自定义分配器(自己写分配器)
void func()
{
list <int, allocator<int>> mylist1;
list <double, allocator<double>> mylist2;
}
}
迭代器的概念和分类
一:迭代器基本概念:
迭代器到底是个啥:迭代器是一个“课遍历STL容器全部或者部分元素”的对象(行为类似于指针的对象);
迭代器用来表现容器中的某一个位置;迭代器紧密依赖于容器,迭代器是由容器来提供的,也就是说,一般来讲,是容器里边定义着迭代器的具体类型细节;
大家理解成迭代器是和容器紧密相关(绑定);
int *p; p = ... printf(*p); iter指向容器中元素; *iter :打印迭代器所指向容器中的元素内容;
namespace _nmsp1
{
void func()
{
vector<int> iv = { 100,200,300 }; //定义一个容器
for (vector<int>::iterator iter = iv.begin(); iter != iv.end(); ++iter)
{
cout << *iter << endl;
}
return;
}
}
二:迭代器的分类:迭代器是分种类的
分类的依据:依据是 迭代器的移动特性以及在这个迭代器上能够做的操作;
迭代器,行为如指针,到处跳,表示一个位置,我们一般分类是依据他的跳跃能力,每个分类是一个对应的struct定义:
a)输出型迭代器:(Output iterator)
struct output_iterator_tag;
b)输入型迭代器:(Input iterator)
struct input_iterator_tag;
c)前向迭代器(Forward iterator)
struct forward_iterator_tag;
d)双向迭代器(Bidirectional iterator)
struct bidirectional_iterator_tag
e)随机访问迭代器(Random-access iterator)
struct random_access_iterator_tag
这些分类(结构)都有继承关系的:
vector<int>::iterator iter = .......
list<int>::iterator iter = ......
大多数容器里边都有一个::iterator迭代器类型;并不是所有容器里都有迭代器;比如stack,queue这种容器就不提供迭代器;
//验证迭代器所属种类的代码:
//如下这些_display_category()是重载函数;
namespace _nmsp2
{
void _display_category(random_access_iterator_tag mytag)
{
cout << "random_access_iterator_tag" << endl;
}
void _display_category(bidirectional_iterator_tag mytag)
{
cout << "bidirectional_iterator_tag" << endl;
}
void _display_category(forward_iterator_tag mytag)
{
cout << "forward_iterator_tag" << endl;
}
void _display_category(output_iterator_tag mytag)
{
cout << "output_iterator_tag" << endl;
}
void _display_category(input_iterator_tag mytag)
{
cout << "input_iterator_tag" << endl;
}
template <typename T>
void display_category(T ite) { //T的类型编译器能推导出来
cout << "---------------begin-------------------" << endl;
//整个这个类型叫 过滤器(萃取机),用来获取T迭代器类型的种类;
typename iterator_traits<T>::iterator_category cagy; //相当于获取迭代器种类;
_display_category(cagy); //编译器会挑选一个最适合的参数的重载_display_category
cout << "typeid(ite).name() = " << typeid(ite).name() << endl; //第三章10节讲rtti时
cout << "---------------end-------------------" << endl;
};
void func() //主函数:
{
display_category(array<int, 100>::iterator()); //这种 类型():代表产生 一个临时对象;
display_category(vector<int>::iterator());
display_category(list<int>::iterator());
display_category(map<int, int>::iterator());
display_category(set<int>::iterator());
}
}
完善迭代器能力:
a)输出型迭代器 struct output_iterator_tag; 一步一步能往前走,并且能够通过这个种类的迭代器来改写容器中的数据;
b)输入型迭代器:struct input_iterator_tag; 一次一个以向前的方向来读取元素,按照这个顺序一个一个返回元素值;
c)前向迭代器:struct forward_iterator_tag;因为继承自从Input迭代器,因此它能以向前的方向来读取元素,并且读取时提供额外保证;
d)双向迭代器:struct bidirectional_iterator_tag:在前向迭代器基础之上增加了往回(反向)迭代,也就是迭代位置可以回退,新增加如下操作:
e)随机访问迭代器:struct random_access_iterator_tag:在双向迭代器基础上又增加了所谓的随机访问能力:也就是增减某个偏移量,能够计算距离,还支持一些关系运算等等;
namespace _nmsp3
{
void func()
{
vector<int> iv = { 100,200,300 };
for (auto iter = iv.begin(); iter != iv.end(); ++iter)
{
cout << *iter << endl;
*iter = 6;
}
int abc;
abc = 0;
}
}
int main()
{
//_nmsp1::func();
//_nmsp2::func();
_nmsp3::func();
return 1;
}