• 【STL学习笔记】一、STL体系


    目录

     

    1.标准库以header files形式呈现

    2.namespce命名空间

    3.STL与OO

    4.STL六组件及其关系

    5.STL组件例子

    6.range-based for statement(c++11)例子

    7.Cout ,long转string的例子


     

    c++标准库包含STL。

    1.标准库以header files形式呈现

    1. c++标准库 #include<vector> 不带.h

    2. 新C #include<cstdio> 不带.h 前面加c

    3. 旧C #include<stdio.h> 带.h 仍然可用


    2.namespce命名空间

    将你写的class,function,template封装后放入一个namespace里,标准库的新headers的组件封装于std中。旧C headers内的组件不能封装在std中。


    3.STL与OO

    某种程度上,STL的概念与面向对象编程的原则相背, STL数据和算法是分离的而不是结合。

    OO是把数据和算法放在一个class里面。
    STL将数据和算法分开。 数据存储在容器里,使用算法进行操作。迭代器是这两者之间的粘合剂,让算法与容器可以进行交互。 

    这里写图片描述 


    4.STL六组件及其关系

    容器       Containers,存放数据结构。

    用来管理某个特定对象的集合。每一种容器都有自己的优点和缺点,在项目中根据不同的需求,使用不同的容器。容器可以是数组、链表或者类字典。 


    算法       Algorithms,进行数据处理的模板函数

     用来处理的元素的集合。例如,可以进行搜索、排序等操作。

    STL提供了一些标准算法来处理集合元素。这些算法一般提供最基本的功能,如搜索、排序、复制、修改和数值处理。

    算法不是容器类的成员函数,而是全局函数。算法可以操作不同容器类型的元素,甚至可以操作用户自定义的容器类型。总之,既减少了代码量,又增强了性能。


    迭代器    Iterators,  相当一种泛化的指针。

    用于遍历对象集合的元素。这些集合可以是容器或容器的子集。每一个容器类都提供了它自己的迭代器类型。

    根据迭代器所支持的操作,一般分为下面5种。 

    1. 前向迭代器只能利用递增运算符进行前向迭代。像unordered_set、unordered_multiset、unordered_map和unordered_multimap这些容器都“至少”是用前向迭代器(某些情况下可以提供双向迭代器)。 
    2. 双向迭代器是可以用递增运算符向前迭代,或者用递减运算符向后迭代。像list、set、multiset、map和multimap的迭代器都是双向迭代器。 
    3. 随机访问迭代器具有双向迭代器的所有属性。此外,他们还可以进行随机访问。这种迭代器本身支持运算操作,可以改变偏移量,也可以利用关系运算符(< 和 >)比较迭代器。像vector、deque、array和string的迭代器都是这类迭代器。 
    4. 输入迭代器能够在迭代时读取或处理一些值。如Input stream iterators。 
    5. 输出迭代器能够在迭代时输出一些值。如Inserters、和output stream iterators。 

    分配器    Allocators,为容器分配内存。


    适配器    Adaptors。 

    1.container adaptor :LIFO stack;FIFO queue;Priority queue

    容器适配器提供顺序容器的特殊接口

    1. stack 堆栈适配器(LIFO) 
    2. queue 改写容器来提供队列(FIFO数据结构) 
    3. priority_queue 改写容器来提供优先级队列

    2.iterator adaptor : move_iterator

    任何操作起来像迭代器的东西都可以当作迭代器。所以可以写出像迭代器的一些类但又执行不一样的操作。C++标准库提供的一些预定义的特殊迭代器,即迭代器适配器。 
    一般分为四类: 
    Insert iterators也称为inserters,用来将“赋值新值”操作转换为“安插新值”操作。通过这种迭代器,算法可以执行安插(insert)行为而非覆盖(overwrite)行为。所有Insert迭代器都隶属于Output迭代器类型,所以它只提供赋值(assign)新值的能力。通常算法会将数值赋值给目的迭代器,如copy()算法 
    Stream iterators是一种迭代器配接器,可以把stream当成算法的原点和终点。更明确的说,一个istream迭代器可以用来从input stream中读元素,而一个ostream迭代器可以用来对output stream写入元素。Stream迭代器的一种特殊形式是所谓的stream缓冲区迭代器,用来对stream缓冲区进行直接读取和写入操作。 
    Reverse iterators重新定义递增运算和递减运算,使其行为正好倒置。 
    Move iterators很像一个底层迭代器(必须至少有一个InputIterator)。如果这个迭代器被当作输入迭代器来用,要注意的是,值的操作是移动而不是复制。

    3.functor Adaptor


    仿函数    Functors。 

    算法函数的参数不一定非要是函数。可以是行为类似函数的对象,称为函数对象,或仿函数


    六组件的关系

    分配器支撑容器,算法通过迭代器控制容器中的数据并处理,仿函数支撑算法。 


    5.STL组件例子

    #include "stdafx.h"
    #include <vector>
    #include <algorithm>
    #include <functional>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	int ia[6] = { 27,210,13,56,109,83 };
    	vector<int, allocator<int>> vi(ia, ia + 6);
    	cout << count_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(),40)));//输出4
    	getchar();
    	return 0;
    }
    
    

    vector<int, allocator<int>> vi(ia, ia + 6);

        1.allocator<int> 每次分配一个int。2.不写第二个模板参数会默认调用分配器
        3.vi对象设初值 头跟尾 vi(ia,ia+6) 第二参数指向数组元素的下一个地址。前闭后开的区间。

    cout << count_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(),40)));

        1.count_if : algorithm
        2.not1 : function adapter(negator) 取反
        3.bind2nd : function adapter(binder) 绑定 第一个参数是运算符 第二个参数绑定在运算符右边的数
        4.less<int>() : function object 函数
        5.not1(bind2nd(less<int>(),40)) : predicate 判断式


    6.range-based for statement(c++11)例子

    语法:

    for ( declaration :  collection ){
    statement
    }

    例子:

    #include "stdafx.h"
    #include <vector>
    #include <algorithm>
    #include <functional>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    
    	for (int i : {1,2,3})
    	{
    		cout << i << endl;
    	}
    
    
    	double ib[2] = { 2.6 , 7.5 };
    	vector<double> vec(ib,ib+2);
    	for (auto elem : vec) {
    		cout << elem << endl;
    	}
    	for ( auto& elem : vec) {
    		elem *= 3;
    		cout << elem << endl;
    	}
    	getchar();
    	return 0;
    }
    

    输出结果:

    1
    2
    3
    2.6
    7.5
    7.8
    22.5

     解读

    1.  for (auto elem : vec) 

    auto在这里是  double

    有时候会是container<T>::iterator 很长,就用auto自动推导。

    2.    for ( auto& elem : vec) 

    auto&是引用,是代表,假象,这里面做的操作就是直接对对象的真实地址进行操作。


    7.Cout ,long转string的例子

    #include "stdafx.h"
    #include <vector>
    #include <list>
    #include <algorithm>
    #include <functional>
    #include <iostream>
    
    using namespace std;
    
    namespace container_test {
    	long get_a_target_long()
    	{
    		long target = 0;
    		cout << "long(0~" << RAND_MAX << "):" << endl;
    		cin >> target;
    		//cout << target << endl;
    		return target;
    	}
    
    
    	string get_a_target_string()
    	{
    		long target = 0;
    		char buf[10];
    		cout << "string (0~" << RAND_MAX << "):" << endl;
    		cin >> target;
    		snprintf(buf, 10, "%d", target);//将格式化的数据写入字符串/参数:输出的存储位置,可存储的最多字符数,格式化字符串
    		//cout << buf << endl;
    		return string(buf);
    	}
    
    	int compareLongs(const void* a, const void* b)
    	{
    		cout << "comparelongs:" << endl;
    		return (*(long*)a - *(long*)b);
    	}
    
    	int compareStrings(const void* a, const void* b)
    	{
    		cout << "comparestring:" << endl;
    		if (*(string*)a > *(string*)b)
    			return 1;
    		else if (*(string*)a < *(string*)b)
    			return -1;
    		else
    			return 0;
    	}
    }
    using namespace  container_test;
    
    int main()
    {
        long a = get_a_target_long();
    	long b = get_a_target_long();
    	string sa = get_a_target_string();
    	getchar();
    	string sb = get_a_target_string();
    
    	cout << compareLongs(&a, &b) << endl << compareStrings(&sa, &sb) << endl;
    
    	return 0;
    }

    输出结果:

    long(0~32767):
    12
    long(0~32767):
    13
    string (0~32767):
    13
    string (0~32767):
    14
    comparestring:
    comparelongs:
    -1
    -1 

    解读:

    1.cout : 调用是从右往左,输出是从左往右(stack)  

    2.如果向long型变量输入字符串,变量只会接受 第一个字符之前的数字。cin>>target ;输入0a,target=0

      

     

     

  • 相关阅读:
    c# HexStringtoByte十六进制字符串转字节与modusCRC校验
    安卓app_sl4_4星级评分条示范代码
    安卓app_sl3_28同意显示开始按钮示范
    安卓app_sl3_27通过ImageView显示带边边框的图片
    关于命令RGZPFM
    (转)经典中的经典
    Shell 截取文件名和后缀
    漫话:如何给女朋友解释什么是CDN?
    使用Shell遍历目录及其子目录中的所有文件
    Linux tr命令使用方法
  • 原文地址:https://www.cnblogs.com/lightmare/p/10425108.html
Copyright © 2020-2023  润新知