STL库学习 参考大道至简(更新完毕)

     @DavidHan ,
     http://blog.csdn.net/david_han008/article/details/72811897

STL组件

  1. 容器
    1. vector<T>向量
    2. list<T>双向链表
    3. queue<T>队列
    4. stack<T>
    5. deque<T>双向队列
    6. priority_queue<T>按值排序队列
    7. set<T>集合(不允许出现重复)
    8. multiset<T>允许出现重复的集合
    9. map<key,val>关联数组容器
    10. multimap<key,val>允许出现key对应着多个val的容器

2.算法
3.迭代器
4.仿函数
5.内存配置器和配接器


字符串的使用

  1. 构造函数
    string strs //生成空字符串
    string strs(str) //生成str字符串的复制品
    string strs(str,begin,end) //生成str字符串从begin到end的字符串

举例说明

 #include <iostream>
 #include <string>
using namespace std;
int main()
{

    string str("abcdefgh");
    string str1(str);
    string str2(str,2,4);
    string str3(str, 4);
    cout <<"str1:"<< str1 << endl;
    cout << "str2:" << str2 << endl;
    getchar();
    return 0;
}
2.大小和容量 2. size()和length()函数返回string类型对象中字符的个数 3. max_size()返回的string 类型中包换最多的字符数 4. capacity()返回的是重新分配内存之间,string对象能包含的最大的是字符数 5. reserve()函数,是为string类型重新分配内存 举例

 #include <iostream>
 #include <string>
using namespace std;
int main()
{
    string str("123456789");
    int size = 0;
    int length = 0;
    size = str.size();
    length = str.length();
    cout << "size:"<<size<< endl;
    cout << "length:" << length << endl;
    getchar();
    return 0;
}

**输出结果size:9 length:9** 3.元素存取 1. [] 2. at函数 注意第一个位置是从0开始计数 最大访问是length()-1 举例
 #include <iostream>
 #include <string>
 using namespace std;
int main()
{
    string str("123456789");
    char num;
    char temp ;
    num = str[0];
    temp = str.at(0);
    cout << "num:"<<num<< endl;
    cout << "temp:" << temp<< endl;
    getchar();
    return 0;
}
**输出结果num:1 temp:1** 4.字符串比较 1. >,
 equal函数
 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
using namespace std;
int main()
{
    vector<int> mvt1;
    //赋初值
    mvt1.push_back(1);
    mvt1.push_back(2);
    mvt1.push_back(3);
    mvt1.push_back(4);
    mvt1.push_back(-1);
    mvt1.push_back(-3);
    //统计等于1的元素个数
    vector<int> mvt2;
    //赋初值
    mvt2.push_back(1);
    mvt2.push_back(3);
    mvt2.push_back(3);
    mvt2.push_back(4);
    mvt2.push_back(-1);
    mvt2.push_back(-3);
    bool eq = std::equal(mvt1.begin(), mvt1.end(), mvt2.begin());
    if (eq)
    {
        cout << "same" << endl;
    } 
    else
    {
        cout << "not same" << endl;
    }
    cin.get();
    return 0;
}

copy函数能够将指定范围内的所有的元素赋值到另一个容器(正序)
copy_back函数,从指定范围的最后一个元素到第一个元素。(逆序)
transform函数将指定范围的元素赋值到目标区间,复制和修改同时进行。

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
void print(int &elment)
{
    std::cout << elment << ",";
}
int main()
{
    int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> mvt;
    mvt.assign(dim, dim + 9);
    std::cout << "vector1:";
    for_each(mvt.begin(), mvt.end(), print);
    std::list<int> mylist1;
    //将所有的元素乘以-1
    std::transform(mvt.begin(), mvt.end(), back_inserter(mylist1), std::negate<int>());
    std::cout << std::endl;
    std::cout << "mylist1*(-1):";
    for_each(mylist1.begin(), mylist1.end(), print);
    //将所有的元素都乘以10
    std::transform(mylist1.begin(), mylist1.end(), mylist1.begin(), std::bind2nd(std::multiplies<int>(), 10));
    std::cout << std::endl;
    std::cout << "mylist1*10:";
    for_each(mylist1.begin(), mylist1.end(), print);
    //将所有的元素都除以2,并且逆序输出
    std::cout << std::endl;
    std::cout << "mylist1 /2:";
    std::transform(mylist1.rbegin(), mylist1.rend(), std::ostream_iterator<int>(std::cout, ","), std::bind2nd(std::divides<int>(), 2));
    std::cin.get();
    return 0;
}

同样也可以利用仿函数,对需要的东西运算进行
补充:

函数模板的一般形式如下:

Template <class或者也可以用typename T>

例如:
template <class T>    
const T MAX(T a , T b)  
{  
    printf("%s\n" , "template") ;  
    return (a > b) ? a : b ;       

}  
模板类
template <class T>  
class Base  
{  
public :      
    T a ;  
    Base(T b)  
    {  
        a = b ;      
    }     
    T getA(){ return a ;} //类内定义   
    void setA(T c);  
};  

template <class T>   //模板在类外的定义   
void  Base<T>::setA(T c)  
{  
    a = c ;  
}  

swap函数可以实现将两个函数进行互换。
fill()函数 fill_n()函数,generate()函数、generate_n()函数用于容器赋值。fin_n函数和generate_n函数给指定区间的前n个数值进行赋值。当然你也可以指定自己的算法,来作为generate的子进程。
举例:

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
int main()
{
    std::vector<int> mvt;
    std::vector<int> mvt2(5, 0), mvt3(6, 0);
    int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    //原始的数据
    mvt.assign(dim, dim + 9);
    std::cout << "mvt:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::cout << "mvt2:";
    std::copy(mvt2.begin(), mvt2.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::cout << "mvt3:";
    std::copy(mvt3.begin(), mvt3.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    //下面开始改变
    std::fill(mvt.begin(), mvt.end(), 9);//将所有的值都赋值成9
    std::cout << "mvt_fill:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::fill_n(mvt.begin(), 3, 6);//产生3个6,其他不变
    std::cout << "mvt_fill_n:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::generate(mvt2.begin(), mvt2.end(), rand);//产生随机数
    std::cout << "mvt2_generate:";
    std::copy(mvt2.begin(), mvt2.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::generate_n(mvt3.begin(), 3, rand);//将前3个数生成随机数
    std::cout << "mvt3_generate_n:";
    std::copy(mvt3.begin(), mvt3.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cin.get();
    return 0;
}

替换使用replace函数

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
int main()
{
    std::vector<int> mvt;
    int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
    //原始的数据
    mvt.assign(dim, dim + 9);
    std::cout << "mvt:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::replace(mvt.begin(), mvt.end(), 1, 8);//将第1个位置替换成8
    std::cout << "mvt_replace:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cin.get();
    return 0;
}

reverse函数逆转输出

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
int main()
{
    std::vector<int> mvt;
    int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
    //原始的数据
    mvt.assign(dim, dim + 9);
    std::cout << "mvt:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::reverse(mvt.begin(), mvt.end());
    std::cout << "mvt_reverse:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cin.get();
    return 0;
}

旋转,也就是将后面的一部分移动到前面来,利用rotate函数。

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
int main()
{
    std::vector<int> mvt;
    int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
    //原始的数据
    mvt.assign(dim, dim + 9);
    std::cout << "mvt:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::rotate(mvt.begin(), mvt.begin() + 3, mvt.end());//输出4,5,6,7,8,9,1,2,3
    std::cout << "mvt_roate:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cin.get();
    return 0;
}

全局排序,利用sort()函数和stable_sort()函数
局部排序,利用partial_sort()和partial_sort_copy()函数,经过partial_sort函数排序之后,有序的元素将会放到前面,无序的函数将会放到后面。partial_sort函数默认是降序排列。
举例:从下面的例子看出,将前面3个数列将最小的三个数进行从小到大排序,排序后的元素放在前面,未排序的元素方面后面

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
int main()
{
    std::vector<int> mvt;
    int dim[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
    //原始的数据
    mvt.assign(dim, dim + 9);
    std::cout << "mvt:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cout << std::endl;
    std::partial_sort(mvt.begin(), mvt.begin() + 3, mvt.end());//输出1,2,3,9,8,7,6,5,4
    std::cout << "mvt_partial_sort:";
    std::copy(mvt.begin(), mvt.end(), std::ostream_iterator<int>(std::cout, ","));
    std::cin.get();
    return 0;
}

根据某个元素排序
nth_element,可以对指定区间内的算法进行排序
堆的内部数据结构是二叉树,下面举例说明
make_head()函数,用来将元素转化为堆
push_heap()函数,在堆上插入一个元素
pop_heap()函数,删除迭代器上最大的元素
sort_heap()函数,对迭代器指定范围内的元素进行排序

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
int main()
{
    std::vector<int> mvt1;
    int dim[] = { 1, 2, 3, 4, 5 };
    mvt1.assign(dim, dim + 5);
    std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator<int>(std::cout, ","));// 1 2 3 4 5
    std::make_heap(mvt1.begin(), mvt1.end());
    //make_heap之后,数据通过二叉树进行存储。
    std::cout << std::endl;
    std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator<int>(std::cout, ","));//5 4 3 1 2
    //pop_heap()函数,删除最后一个,说明在堆中最后一个元素是5
    std::cout << std::endl;
    pop_heap(mvt1.begin(), mvt1.end());
    mvt1.pop_back();
    //POP_HEAD之后
    std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator<int>(std::cout, ","));//4 2 3 1
    std::cout << std::endl;
    //push_heap函数
    mvt1.push_back(8);
    push_heap(mvt1.begin(), mvt1.end());
    std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator<int>(std::cout, ","));//8 4 3 1 2
    std::cout << std::endl;
    //sort函数之后
    sort(mvt1.begin(), mvt1.end());
    std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator<int>(std::cout, ","));//1 2 3 4 8
    std::cin.get();
    return 0;
}

容器的操作,交并补差。merge函数将两个容器合并 set_union函数,用于实现两个有序内元素的合并。set_intersection函数,用于实现交集 set_diffence实现两个容器的差集。
搜索算法,binary_search函数,实现有序区间内,搜索指定元素 include函数检查在这个区间内是否存在某个元素。lower_bound函数返回第一个大于value的值。equal_rande函数和lower_bound函数一样,但是要求序列有序。,如果未找到指定元素,则返回容器的最后一个值。
删除算法,remove函数,直接将元素进行删除。remove_if函数,用于移除判断式为true的元素。被删除之后,其他元素会自动向前。remove_copy函数,是将remove函数,和copy函数,并且进行复制。
unique函数用于移除重复元素 unique_copy函数用于在复制过程中移除相关元素。
逆向迭代器 list<int>::reverse_iterator itR (it)后面的括号是指赋值。
迭代器饿辅助函数:advance函数,可以使得相关的迭代器前进或后退一个或多个元素。

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
int main()
{
    std::vector<int> mvt1;
    int dim[] = { 1, 2, 3, 4, 5 };
    mvt1.assign(dim, dim + 5);
    std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator<int>(std::cout, ","));// 1 2 3 4 5
    std::vector<int>::iterator it;
    std::cout << std::endl;
    it = mvt1.begin();//迭代器指向的位置
    std::cout << "it:" << *it << std::endl;
    std::advance(it, 2);//后移两个位置
    std::cout << "it:" << *it << std::endl;
    std::cin.get();
    return 0;
}

distance函数,计算两个迭代器的位置

 #include<vector>
 #include<algorithm>
 #include<iostream>
 #include<functional>
 #include<list>
 #include<iterator>
int main()
{
    std::vector<int> mvt1;
    int dim[] = { 1, 2, 3, 4, 5 };
    mvt1.assign(dim, dim + 5);
    std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator<int>(std::cout, ","));// 1 2 3 4 5
    std::vector<int>::iterator pos1;
    pos1 = std::find(mvt1.begin(), mvt1.end(), 2);
    std::vector<int>::iterator pos2;
    pos2 = std::find(mvt1.begin(), mvt1.end(), 5);
    std::cout << std::endl;
    std::cout << distance(pos1, pos2) << std::endl;//输出3
    std::cin.get();
    return 0;
}

iter_swap函数用来交换两个迭代器指向的内容。
复数的计算
注意complex的类型最好是double类型

 #include <complex>
 #include <iostream>
int main()
{
    std::complex<double> c1(3.0, 4.0);//定义实部和虚部
    std::complex<double> c2(std::polar(1.1, 2.2));//利用长度和半径进行初始化
    std::cout << c1 << std::endl;
    std::cout << c2 << std::endl;
    std::cout << "C1的模值:" << std::abs(c1) <<"相位是:"<<std::arg(c1) << std::endl;
    double re = 6.0;
    double im = 8.0;
    c2.real(re);
    c2.imag(im);
    std::cin.get();
    std::cout << "C1的模值:" << std::abs(c1) <<"相位是:"<<std::arg(c1) << std::endl;
    return 0;
}

复数的计算
abs函数求复数的模,
norm函数复数模的平方
arg函数复数的相位
conj函数共轭复数
polar函数极坐标
sin函数
cos函数
tan函数
sinh函数双曲正弦
cosh函数双曲余弦
tanh函数双曲正切
pow幂函数c2 = std::pow(c2, 2);
exp函数,e的指数次c2 = std::exp(c2);
log函数是以e为底的对数
log10函数是以10为底的对数
向量的运算
valarray

 #include<valarray>
 #include <iostream>
int main()
{   
    int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8,9, };
    std::valarray<int> val1(dim,sizeof(dim)/sizeof(int));
    std::cout << val1.max() << std::endl;//输出最大值
    std::cin.get();
    return 0;
}

size()函数用来获取数组的大小
sum函数用来对数组中所有的元素求和
resize函数用来重新设置数组的大小
shift函数实现逻辑移位,cshift函数实现循环移位,这里移位指将数组中的元素的顺序进行移动。
apply函数 valarry<T> apply(<T> fn)对fn函数处理数组中的每个元素、
free函数,删除数组当中所有元素,并且能够数组的长度设置为0
下面这个例子很经典。

 #include<valarray>
 #include <iostream>
int fn(int ele)
{
    int r =0;
    r = ele * 2;
    return r;
}
void print(std::valarray<int> &val)
{
    int size = val.size();
    for (int i = 0; i < size;i++)
    {
        std::cout << val[i] << ",";
    }
    std:: cout<< std::endl;
}
int main()
{   
    int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8,9, };
    std::valarray<int> val1(dim,sizeof(dim)/sizeof(int));
    print(val1);
    val1 = val1.apply(&fn);
    print(val1);
    std::cin.get();
    return 0;
}

对于valarry而言,除了一般的sin,cos等,还可以使用atan函数(反切正弦)和atan2函数(这个函数返回值是方位角)函数atan2(y,x)中参数的顺序是倒置的,atan2(y,x)计算的值相当于点(x,y)的角度值。
slice从一个数组当中提取部分元素,称为一个新的子集。
补充一下valarry的操作std::valarray<int> val(10,4);输出4个10,std::valarray<int> val(10;输出10个0

举例说明:

 #include<valarray>
 #include <iostream>
void print(std::valarray<int> &val)
{
    int size = val.size();
    for (int i = 0; i < size;i++)
    {
        std::cout << val[i] << ",";
    }
    std:: cout<< std::endl;
}
int main()
{   
    int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8,9, };
    //方式1
    std::valarray<int> val1(dim,sizeof(dim)/sizeof(int));
    std::valarray<int> val2 = std::valarray<int>(val1[std::slice(2, 4, 1)]);//输出3,4,5,6//slice函数的三个参数。起始下标,元素个数,元素的间隔
    //方式2
    std::slice myslice(2, 4, 1);
    std::valarray<int> val3 = val1[myslice];//输出3,4,5,6
    print(val3);
    print(val2);
    std::cin.get();
    return 0;
}

gslice函数与slice函数一维数据是一致的,gslice函数可以表示二维,三维甚至高维数据。

#include<valarray>
 #include <iostream>
 #include <string>
using namespace std;
void print(std::valarray<int> &val)
{
    int size = val.size();
    for (int i = 0; i < size;i++)
    {
        std::cout << val[i] << ",";
    }
    std:: cout<< std::endl;
}
int main()
{   
    valarray<int> val_1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
    //二维数据
    /************************************************************************/
    /* 生成一个2*4的数据,
    *&&&& 用2,5生成两个数,1,6,然后在用4,3生成每行生成4个数,间隔3
     &&&&*/
    /************************************************************************/
    valarray<size_t> len1 = { 2 ,4}, stride1 = { 5,3};
    valarray<int>  val_2 = val_1[gslice(0, len1, stride1)];
    print(val_2);//输出1 4 7 10 6 9 12 15
    std::cin.get();
    return 0;
}

mask_array的屏蔽子集

 #include<valarray>
 #include <iostream>
 #include <string>
using namespace std;
void print(std::valarray<int> &val)
{
    int size = val.size();
    for (int i = 0; i < size;i++)
    {
        std::cout << val[i] << ",";
    }
    std:: cout<< std::endl;
}
int main()
{   
    valarray<int> val_1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 },val2;
    bool B[] = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
    std::valarray<bool> mask_array(B, 9);//输出前9个数
    val2 = val_1[mask_array];//输出结果2 4 6 8
    print(val2);
    std::cin.get();
    return 0;
}

STL当中也提供的内积等运算,如果觉得麻烦,我觉得复杂运算就用Eigen。
accumulate函数求容器的和,partial_sum函数对指定范围内函数进行部分求和。adjacent_difference函数计算序列的差

 #include <iostream>
 #include<algorithm>
 #include<functional>
 #include<numeric>
 #include <vector>
 #include<iterator>
using namespace std;
void print(std::vector<int> &val)
{
    int size = val.size();
    for (int i = 0; i < size;i++)
    {
        std::cout << val[i] << ",";
    }
    std:: cout<< std::endl;
}
int myop(int orig,int ele)
{
    return ele * 2 + orig;
}
int main()
{   
    std::vector<int> val1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> val2, val3, val4,val5;
    print(val1);
    //输出90
    int sum = std::accumulate(val1.begin(), val1.end(), 0, myop);//这里的0表示的多加的值,一般在这里设置成0就可以
    std::cout << sum << std::endl;
    //输出45
    int sum2= std::accumulate(val1.begin(), val1.end(), 0);//这里的0表示的多加的值,一般在这里设置成0就可以
    std::cout << sum2 << std::endl;
    //部分求和
    partial_sum(val1.begin(), val1.end(), back_inserter(val2));
    print(val2);
    partial_sum(val1.begin(), val1.end(), back_inserter(val3),myop);
    print(val3);
    //部分求差
    adjacent_difference(val1.begin(), val1.end(), back_inserter(val4));
    print(val4);
    adjacent_difference(val1.begin(), val1.end(), back_inserter(val5),myop);
    print(val5);
    std::cin.get();
    return 0;
}

输出结果:
这里写图片描述
输入输出模板:
flush表示刷新缓冲区std::cout<<std::flush<<std::endl;
精确到小数std::cout.precision(6)
八进制显示std::oct
十六进制显示std::hex
十进制显示std::dec
abort函数,执行弹出对话框,终止程序,exit函数不会弹出对话框,直接终止程序。
异常处理
异常处理的关键字,try-catch中间包含throw

function()
{
    throw 表示式;
}
try{ 
    function();
}
catch(异常发生的情况1)
{
}
catch(异常发生的情况2)
{
}

pairs 对组
使用make_pair函数可以生成一个pair对象std::make_pair('abc',13);他和std::pair<stirng,int>('abc',13);的效果是一样的
size_t表示一种无正负号的类型,用于表示元素个数
ptrdiff_t表示一种带有正负号的类型,用于表示指针之间的距离
offsetof表示一个成员在结构体或者联合体中的偏移量。
时间和日期
asctime,ctime函数,将指定的时间用字符串形式输出,difftime函数,返回两个时刻的间隔。time函数,返回系统的当中时间

#pragma warning(disable : 4996)
 #include<ctime>
 #include <iostream>
 #include <chrono>
int main()
{
    struct tm* mtime;//定义个一个结构体,用来存数据
    time_t myclock;//定义一个time_t类型的用来读取localtime
    time(&myclock);
    long count = 6000000L;
    mtime = std::localtime(&myclock);
    std::cout << "asctime:" <<std::asctime(mtime) << std::endl;//使用asctime函数
    std::cout << "time:" << std::ctime(&myclock) << std::endl;//使用ctime函数
    clock_t start, finish;
    double duration;
    start = std::clock();//获取当前时间
    while (count--);
    finish = std::clock();//后当前时间   
    duration = (double)(finish - start) / CLOCKS_PER_SEC;//将单位转化成秒,j精确到毫秒,这里可以用于计算算法的时间
    std::cout << ":" << duration << "s" << std::endl;
    //这是第二种方式,这里的单位是s
    time_t tstart, tfinish, tcurr;
    count = 600000000L;
    time(&tstart);
    while (count--);
    time(&tfinish);
    duration = tfinish - tstart;
    std::cout << ":" << duration << "s" << std::endl;
    std::cin.get();
    return 0;
}

仿函数,是将函数作为参数传递的方式。
一元组合函数配接器

举例说明

 #include<iostream>
 #include<functional>
 #include<vector>
 #include<algorithm>
 #include<iterator>
template <class op1,class op2> // compose_f_gx_t继承自后面的类
class compose_f_gx_t : public std::unary_function<typename op2::argument_type, typename op1::result_type>
{
private:
    op1 myop1;
    op2 myop2;
public:
    compose_f_gx_t(const op1 &o1, const op2 &o2) :myop1(o1), myop2(o2)
    {}
    typename op1::result_type operator() (const typename op2::argument_type &x) const   //这里是说明一个仿函数
    {
        return myop1(myop2(x));
    }
};//通过内联函数实现
template <class op1, class op2> inline compose_f_gx_t<op1, op2>compose_f_gx(const op1 &o1, const op2 &o2)
{
    return compose_f_gx_t<op1, op2>(o1, o2);
}
void myprint(std::vector<int> &vt)
{
    std::vector<int>::iterator it;
    for (it = vt.begin(); it != vt.end();it++)
    {
        std::cout << *it << ",";
        std::cout << std::endl;
    }
}
int main()
{
    std::vector<int> vt;
    int array[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    vt.assign(array, array + 9);
    myprint(vt);
    std::transform(vt.begin(), vt.end(), std::ostream_iterator<int>(std::cout, ","), compose_f_gx(std::bind2nd(std::multiplies<int>(), 5), std::bind2nd(std::plus<int>(), 10)));
    std::cin.get();
    return 0;
}

谓词
返回的类型是bool的仿函数

template <class T> struct logical_not :public unary_function<T, bool>{

    bool operator()(const T &x) const
    {
        return !x;
    }
};
template <class T> struct less:public binary_function<T,T,bool>
{
    bool operator()(const T &x, const T&y) const
    {
        return x < y;
    }
};

仿函数identity

 #include<iostream>
 #include <functional>
 #include<assert.h>
int main()
{
    int x = 137;
    std::identity<int> id;
    //assert函数,如果返回的false,则终止程序
    assert(x == id(x));
    std::cout << id(x) << std::endl;//输出结果137
    std::cin.get();
    return 0;
}

适配器
1、绑定器:bind1st函数(将第一个参数绑定到实参上)、bind2nd函数(将第2个参数绑定到实参上)
2、取反器,not1函数(翻转一元函数的值)和not2函数(翻转二元函数的值)
3、成员函数适配器
4、函数指针适配器
配置器(内存配置器allocator)
原子运行库模板atomic 的操作

 #include<iostream>
 #include<atomic>
int main()
{
    std::cout << "初始值:";
    std::atomic<int> aa(0);
    std::cout << aa.load() << std::endl;
    std::atomic_init(&aa, 50);
    std::cout << "init之后:" << aa.load() << std::endl;
    aa.store(100);
    std::cout << "store:" << aa.load() << std::endl;
    std::atomic_fetch_add(&aa, 25);
    std::cout << "add:" << aa.load() << std::endl;//输出125
    bool y = std::atomic_is_lock_free(&aa);
    std::cout << "bool:" << y << std::endl;
    std::cin.get();
    return 0;
}

原子类型的标志位atomic_flag的使用。

 #include<iostream>
 #include<atomic>
 #include<thread>
 #include<sstream>
 #include<vector>
int main()
{
    std::atomic_flag lock = ATOMIC_FLAG_INIT;
    bool set = atomic_flag_test_and_set(&lock);
    std::cout << "lock ? :" << set << std::endl;//输出0
    std::cout << "lock value:" << lock._My_flag << std::endl;//输出1
    atomic_flag_clear(&lock);
    std::cout << "lock is value:" << lock._My_flag << std:endl;//输出0
    std::cin.get();
    return 0;
}

线程控制类模板
构造线程thread()
线程析构~thread()
交换本线程和其他线程之间的状态swap()
判断本线程能用用于执行joinable()
将线程加入程序进行执行join
线程启动后,若执行detach函数,,则不等待线程返回,继续执行程序。detach()
线程命名空间下的成员函数:get_id()用于返回当前执行线程的唯一标识,yield()重新提供调度机会,暂停本线程的运行,允许其他线程和进行执行。sleep_untile函数在多少秒之后,开始阻塞线程。sleep_for阻塞当前线程多少秒

 #include<iostream>
 #include<thread>
int thread_id = 0;
void thread_task_add()
{
    thread_id++;
    std::cout << "线程增加的次数:" << thread_id << std::endl;
}
void thread_task_pub()
{
    thread_id--;
    std::cout << "线程减少的次数:" << thread_id << std::endl;
}
int main()
{
    //创建一个线程
    std::thread t(thread_task_add);
    t.join();
    std::thread t2(thread_task_pub);
    t2.join();
    std::cin.get();
    return 0;
}

互斥:mutex,recursive_mutex递归型、timed_mutex超时型、recursive_timed_mutex递归并且超时型
mutex的意义在于,在多线程之间保护数据,并确保数据的同步性。

#include<iostream>
 #include<thread>
 #include<mutex>
std::mutex m, m2;
long data[12];
void thread_proc1()
{
    int index = 0;
    for (int index = 0; index < 5; index++)
    {
        m.try_lock();
        data[2 * index] = 2 * index;
        std::cout << "fdfd:" << data[2 * index] << std::endl;
        m.unlock();
        std::chrono::microseconds sd(10);
        std::this_thread::sleep_for(sd);
    }
    std::cout << "线程1结束" << std::endl;
}
void thread_proc2()
{
    int index2 = 0;
    for (int index2 = 0; index2 < 5; index2++)
    {
        m.lock();
        data[2* index2+1] = 2 * index2+1;
        std::cout << "fdfd:" << data[2 * index2+1] << std::endl;
        m.unlock();
        std::chrono::microseconds sd(10);
        std::this_thread::sleep_for(sd);
    }
    std::cout << "线程2结束" << std::endl;
}
int main()
{
    std::thread t(thread_proc1);
    std::thread t2(thread_proc2);
    t.detach();
    t2.join();
    std::cin.get();
    return 0;
}

这里写图片描述
利用递归互斥锁recursive_mutex

 #include<iostream>
 #include<thread>
 #include<mutex>
 #include<chrono>
std::recursive_mutex mt;
long dim[11];
void mysleep(long ms)
{
    std::chrono::milliseconds md(10);
    std::this_thread::sleep_for(md);
}
void thread_proc1()
{
    int index = 0;
    for (index = 0; index < 5;index++)
    {
        mt.lock();
        dim[index * 2] = 1;
        std::cout << "线程1num:" << dim[index * 2 + 1] << std::endl;
        mt.unlock();
        mysleep(10);
    }
    std::cout << "结束线程1" << std::endl;
}
void thread_proc2()
{
    int index2 = 0;
    for (index2 = 0; index2 < 5;index2++)
    {
        mt.lock();
        dim[index2 * 2 + 1] = 2;
        std::cout << "线程2num:" << dim[index2 * 2 + 1] << std::endl;
        mt.unlock();
        mysleep(10);
    }
    std::cout << "结束线程2" << std::endl;
}

int main()
{
    std::thread t1(thread_proc1);
    std::thread t2(thread_proc2);
    t1.join();
    t2.join();
    std::cin.get();
    return 0;
}

这里写图片描述
缺点是,上面两个线程的竞争是混乱的。输出也是无序的。
定时式互斥对象类time_mutex
利用try_lock_for函数,函数参数是输入的时间,若线程没有获得锁,则线程被阻塞相应的时间

 #include<iostream>
 #include<thread>
 #include<mutex>
 #include<chrono>
std::timed_mutex tm;
void job1()
{
    bool b1 = 0;
    int count = 5;
    while (count--)
    {
        b1 = tm.try_lock_for(std::chrono::microseconds(10));
        std::cout << "线程1的count:"<<count << std::endl;
        if (b1)
            tm.unlock();
    }
    std::cout << "线程1结束" << std::endl;
}
void job2()
{
    int count = 5;
    bool b1 = 0;
    while (count--)
    {
        b1 = tm.try_lock_for(std::chrono::microseconds(10));
        std::cout << "线程2的count:" << count << std::endl;
        if (b1)
            tm.unlock();
    }
    std::cout << "线程2结束" << std::endl;
}
int main()
{
    std::thread t1(job1);
    std::thread t2(job2);
    t1.join();
    t2.join();
    std::cin.get();
    return 0;
}

这里写图片描述
递归式定时互斥锁

 #include<iostream>
 #include<thread>
 #include<mutex>
 #include<chrono>
std::recursive_timed_mutex rtm;
void my_sleep(short s)
{
    std::this_thread::sleep_for(std::chrono::seconds(s));//按照秒进行修改
}
void job1()
{
    long cnt = 6;
    bool b1;
    while (cnt--)
    {
        b1 = rtm.try_lock();
        if (b1)
        {
            std::cout << "当前线程1的ID:" << std::this_thread::get_id() << std::endl;
            rtm.unlock();
        }
        my_sleep(1);
    }
}
void job2()
{
    long cnt = 6;
    bool b1;
    while (cnt--)
    {
        b1 = rtm.try_lock_for(std::chrono::microseconds(10));
        if (b1)
        {
            std::cout << "当前线程2的ID:" <<std:: this_thread::get_id() << std::endl;
            rtm.unlock();
        }
        my_sleep(1);
    }
}
int main()
{
    std::thread t1(job1);
    std::thread t2(job2);
    t1.join();
    t2.join();
    std::cin.get();
    return 0;
}

这里写图片描述
锁是一种互斥的对象,可以确保锁定对象的引用。lock_guard

 #include<iostream>
 #include<thread>
 #include<mutex>
 #include<chrono>
std::mutex mt;
void my_sleep(short s)
{
    std::this_thread::sleep_for(std::chrono::seconds(s));//按照秒进行修改
}
void job1()
{
    long cnt = 6;
    while (cnt--)
    {
        std::lock_guard<std::mutex> lg(mt);
        std::cout << "线程1的ID:" << std::this_thread::get_id() << std::endl;
        my_sleep(1);
    }
}
void job2()
{
    long cnt = 6;
    while (cnt--)
    {
        mt.lock();
        std::lock_guard<std::mutex> lg(mt,std::adopt_lock);
        std::cout << "线程2的ID:" << std::this_thread::get_id() << std::endl;
        my_sleep(1);
    }
}
int main()
{
    std::thread t1(job1);
    std::thread t2(job2);
    t1.join();
    t2.join();
    std::cin.get();
    return 0;
}

这里写图片描述
call_once函数,表明只允许一个线程进行

#include<iostream>
 #include<thread>
 #include<mutex>
 #include<chrono>
int winner;
std::once_flag winner_flag;
void set_winner(int &x)
{
    winner = x;
    std::cout << "winner" << winner << std::endl;
}
void job1(int &id)
{
    std::call_once(winner_flag, set_winner, id + 2);
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "线程1 的ID:" << id << std::endl;
}
void job2(int &id)
{
    std::call_once(winner_flag, set_winner, id + 2);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "线程2 的ID:" << id << std::endl;
}
int main()
{
    std::thread threads[10];
    for (int i = 0; i < 5; ++i)
        threads[i * 2] = std::thread(job1, i * 2 + 1);
    for (int i = 0; i < 5; ++i)
        threads[i * 2+1] = std::thread(job2, i * 2 + 1+1);
    for (auto&th : threads) th.join();
    std::cin.get();
    return 0;
}

这里写图片描述
条件变量,里面包含的成员函数,wait()用于等待通知,wait_for()用于等待时间长度

 #include<iostream>
 #include<thread>
 #include<mutex>
 #include<chrono>
 #include<condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id(int id)
{
    std::unique_lock<std::mutex> lck(mtx);//初始化
    while (!ready) cv.wait(lck);
    std::cout << "当前线程的ID:" << id << std::endl;
}
void go()
{
    std::unique_lock<std::mutex> lck(mtx);
    ready = true;
    cv.notify_all();
}
int main()
{
    std::thread threads[10];
    for (int i = 0; i < 10; ++i)
        threads[i] = std::thread(print_id, i);
        std::cout << "10个线程准备开始" << std::endl;
        go();
        //自动开启所有线程
    for (auto&th : threads) th.join();
    std::cin.get();
    return 0;
}

这里写图片描述
正则表达式 regex

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值