本文由 @DavidHan 出品,转载请注明出处
文章链接: http://blog.csdn.net/david_han008/article/details/72811897
STL组件
向量
双向链表
队列
栈
双向队列
按值排序队列
集合(不允许出现重复)
允许出现重复的集合
关联数组容器
允许出现key对应着多个val的容器2.算法
3.迭代器
4.仿函数
5.内存配置器和配接器
字符串的使用
string strs //生成空字符串
string strs(str) //生成str字符串的复制品
string strs(str,begin,end) //生成str字符串从begin到end的字符串
举例说明
#include
#include
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
#include
using namespace std;
int main()
{
string str("123456789");
int size = 0;
int length = 0;
size = str.size();
length = str.length();
cout << "size:"<
**输出结果size:9 length:9** 3.元素存取 1. [] 2. at函数 注意第一个位置是从0开始计数 最大访问是length()-1 举例
#include
#include
using namespace std;
int main()
{
string str("123456789");
char num;
char temp ;
num = str[0];
temp = str.at(0);
cout << "num:"<
**输出结果num:1 temp:1** 4.字符串比较 1. >,
equal函数
#include
#include
#include
#include
using namespace std;
int main()
{
vector 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 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
#include
#include
#include
#include
#include
void print(int &elment)
{
std::cout << elment << ",";
}
int main()
{
int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector mvt;
mvt.assign(dim, dim + 9);
std::cout << "vector1:";
for_each(mvt.begin(), mvt.end(), print);
std::list mylist1;
//将所有的元素乘以-1
std::transform(mvt.begin(), mvt.end(), back_inserter(mylist1), std::negate());
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(), 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(std::cout, ","), std::bind2nd(std::divides(), 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::setA(T c)
{
a = c ;
}
swap函数可以实现将两个函数进行互换。
fill()函数 fill_n()函数,generate()函数、generate_n()函数用于容器赋值。fin_n函数和generate_n函数给指定区间的前n个数值进行赋值。当然你也可以指定自己的算法,来作为generate的子进程。
举例:
#include
#include
#include
#include
#include
#include
int main()
{
std::vector mvt;
std::vector 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(std::cout, ","));
std::cout << std::endl;
std::cout << "mvt2:";
std::copy(mvt2.begin(), mvt2.end(), std::ostream_iterator(std::cout, ","));
std::cout << std::endl;
std::cout << "mvt3:";
std::copy(mvt3.begin(), mvt3.end(), std::ostream_iterator(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(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(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(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(std::cout, ","));
std::cin.get();
return 0;
}
替换使用replace函数
#include
#include
#include
#include
#include
#include
int main()
{
std::vector 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(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(std::cout, ","));
std::cin.get();
return 0;
}
reverse函数逆转输出
#include
#include
#include
#include
#include
#include
int main()
{
std::vector 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(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(std::cout, ","));
std::cin.get();
return 0;
}
旋转,也就是将后面的一部分移动到前面来,利用rotate函数。
#include
#include
#include
#include
#include
#include
int main()
{
std::vector 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(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(std::cout, ","));
std::cin.get();
return 0;
}
全局排序,利用sort()函数和stable_sort()函数
局部排序,利用partial_sort()和partial_sort_copy()函数,经过partial_sort函数排序之后,有序的元素将会放到前面,无序的函数将会放到后面。partial_sort函数默认是降序排列。
举例:从下面的例子看出,将前面3个数列将最小的三个数进行从小到大排序,排序后的元素放在前面,未排序的元素方面后面
#include
#include
#include
#include
#include
#include
int main()
{
std::vector 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(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(std::cout, ","));
std::cin.get();
return 0;
}
根据某个元素排序
nth_element,可以对指定区间内的算法进行排序
堆的内部数据结构是二叉树,下面举例说明
make_head()函数,用来将元素转化为堆
push_heap()函数,在堆上插入一个元素
pop_heap()函数,删除迭代器上最大的元素
sort_heap()函数,对迭代器指定范围内的元素进行排序
#include
#include
#include
#include
#include
#include
int main()
{
std::vector mvt1;
int dim[] = { 1, 2, 3, 4, 5 };
mvt1.assign(dim, dim + 5);
std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator(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(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(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(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(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
后面的括号是指赋值。
迭代器饿辅助函数:advance函数,可以使得相关的迭代器前进或后退一个或多个元素。
#include
#include
#include
#include
#include
#include
int main()
{
std::vector mvt1;
int dim[] = { 1, 2, 3, 4, 5 };
mvt1.assign(dim, dim + 5);
std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator(std::cout, ","));// 1 2 3 4 5
std::vector::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
#include
#include
#include
#include
#include
int main()
{
std::vector mvt1;
int dim[] = { 1, 2, 3, 4, 5 };
mvt1.assign(dim, dim + 5);
std::copy(mvt1.begin(), mvt1.end(), std::ostream_iterator(std::cout, ","));// 1 2 3 4 5
std::vector::iterator pos1;
pos1 = std::find(mvt1.begin(), mvt1.end(), 2);
std::vector::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
#include
int main()
{
std::complex c1(3.0, 4.0);//定义实部和虚部
std::complex c2(std::polar(1.1, 2.2));//利用长度和半径进行初始化
std::cout << c1 << std::endl;
std::cout << c2 << std::endl;
std::cout << "C1的模值:" << std::abs(c1) <<"相位是:"<
复数的计算
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
#include
int main()
{
int dim[] = { 1, 2, 3, 4, 5, 6, 7, 8,9, };
std::valarray val1(dim,sizeof(dim)/sizeof(int));
std::cout << val1.max() << std::endl;//输出最大值
std::cin.get();
return 0;
}
size()函数用来获取数组的大小
sum函数用来对数组中所有的元素求和
resize函数用来重新设置数组的大小
shift函数实现逻辑移位,cshift函数实现循环移位,这里移位指将数组中的元素的顺序进行移动。
apply函数 valarry
对fn函数处理数组中的每个元素、
free函数,删除数组当中所有元素,并且能够数组的长度设置为0
下面这个例子很经典。
#include
#include
int fn(int ele)
{
int r =0;
r = ele * 2;
return r;
}
void print(std::valarray &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 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
输出4个10,std::valarray
输出10个0
举例说明:
#include
#include
void print(std::valarray &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 val1(dim,sizeof(dim)/sizeof(int));
std::valarray val2 = std::valarray(val1[std::slice(2, 4, 1)]);//输出3,4,5,6//slice函数的三个参数。起始下标,元素个数,元素的间隔
//方式2
std::slice myslice(2, 4, 1);
std::valarray val3 = val1[myslice];//输出3,4,5,6
print(val3);
print(val2);
std::cin.get();
return 0;
}
gslice函数与slice函数一维数据是一致的,gslice函数可以表示二维,三维甚至高维数据。
#include
#include
#include
using namespace std;
void print(std::valarray &val)
{
int size = val.size();
for (int i = 0; i < size;i++)
{
std::cout << val[i] << ",";
}
std:: cout<< std::endl;
}
int main()
{
valarray 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 len1 = { 2 ,4}, stride1 = { 5,3};
valarray 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
#include
#include
using namespace std;
void print(std::valarray &val)
{
int size = val.size();
for (int i = 0; i < size;i++)
{
std::cout << val[i] << ",";
}
std:: cout<< std::endl;
}
int main()
{
valarray 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 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
#include
#include
#include
#include
#include
using namespace std;
void print(std::vector &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 val1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector 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::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
的效果是一样的
size_t表示一种无正负号的类型,用于表示元素个数
ptrdiff_t表示一种带有正负号的类型,用于表示指针之间的距离
offsetof表示一个成员在结构体或者联合体中的偏移量。
时间和日期
asctime,ctime函数,将指定的时间用字符串形式输出,difftime函数,返回两个时刻的间隔。time函数,返回系统的当中时间
#pragma warning(disable : 4996)
#include
#include
#include
int main()
{
struct tm* mtime;//定义个一个结构体,用来存数据
time_t myclock;//定义一个time_t类型的用来读取localtime
time(&myclock);
long count = 6000000L;
mtime = std::localtime(&myclock);
std::cout << "asctime:" <
仿函数,是将函数作为参数传递的方式。
一元组合函数配接器
举例说明
#include
#include
#include
#include
#include
template // compose_f_gx_t继承自后面的类
class compose_f_gx_t : public std::unary_function
{
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 inline compose_f_gx_tcompose_f_gx(const op1 &o1, const op2 &o2)
{
return compose_f_gx_t(o1, o2);
}
void myprint(std::vector &vt)
{
std::vector::iterator it;
for (it = vt.begin(); it != vt.end();it++)
{
std::cout << *it << ",";
std::cout << std::endl;
}
}
int main()
{
std::vector 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(std::cout, ","), compose_f_gx(std::bind2nd(std::multiplies(), 5), std::bind2nd(std::plus(), 10)));
std::cin.get();
return 0;
}
谓词
返回的类型是bool的仿函数
template <class T> struct logical_not :public unary_functionbool>{
bool operator()(const T &x) const
{
return !x;
}
};
template <class T> struct less:public binary_functionbool>
{
bool operator()(const T &x, const T&y) const
{
return x < y;
}
};
仿函数identity
#include
#include
#include
int main()
{
int x = 137;
std::identity 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
#include
int main()
{
std::cout << "初始值:";
std::atomic 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
#include
#include
#include
#include
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
#include
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
#include
#include
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;
}
#include
#include
#include
#include
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
#include
#include
#include
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:"<
#include
#include
#include
#include
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:" <
锁是一种互斥的对象,可以确保锁定对象的引用。lock_guard
#include
#include
#include
#include
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 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 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;
}
#include
#include
#include
#include
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
#include
#include
#include
#include
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id(int id)
{
std::unique_lock lck(mtx);//初始化
while (!ready) cv.wait(lck);
std::cout << "当前线程的ID:" << id << std::endl;
}
void go()
{
std::unique_lock 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;
}