C++11(下)

C++11(下)

  • 1.条件变量
  • 2.包装器(重要)
  • 3.bind

🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【C++的学习】
📝📝本篇内容:条件变量;包装器;bind
⬆⬆⬆⬆上一篇:C++11(中)
💖💖作者简介:轩情吖,请多多指教(> •̀֊•́ ) ̖́-

1.条件变量

条件变量我们常常用于多线程中,来保证线程的同步异步
☞ 条件变量文档
在这里插入图片描述
我们来使用一下部分函数,我写了一个简单的生产者消费者模型代码,可以参考一下

#include <iostream>
#include <thread>
#include <condition_variable>
#include <stack>
#include <mutex>
#include <cstdlib>
#include <ctime>
#include <Windows.h>
using namespace std;
condition_variable cv_productor;//定义个条件变量,生产者的
condition_variable cv_customer;//定义个条件变量,消费者的
stack<int> container;//存放数据的容器
mutex mtx;
#define SIZE 5
void Productor()
{while (1){unique_lock<mutex> ck(mtx);while (container.size() == SIZE)//如果满足这个条件,线程就会挂起等待{cv_productor.wait(ck);//挂起后等待唤醒}container.push(rand() % 100 + 1);cv_customer.notify_one();//唤醒消费者一个线程//Sleep(1000);}
}void Customer()
{while (1){unique_lock<mutex> ck(mtx);while (container.empty()){cv_customer.wait(ck);}int ret = container.top();container.pop();cout << ret << endl;fflush(stdout);cv_productor.notify_one();//唤醒生产者其中一个线程Sleep(1000);//让消费者慢一点}
}int main()
{srand((unsigned)time(nullptr));thread thread_array_productor[SIZE];for (int i = 0; i < SIZE; i++)//生产者{thread_array_productor[i] = thread(Productor);//创建线程并启动}thread thread_array_customer[SIZE];for (int i = 0; i < SIZE; i++)//消费者{thread_array_customer[i] = thread(Customer);//创建线程并启动}//主线程等待回收线程for (auto& e : thread_array_productor){e.join();}for (auto& e : thread_array_customer){e.join();}return 0;
}

如果对生产消费模型不太理解的,可以看我的另一篇博客☞Linux多线程

2.包装器(重要)

接下来要讲的包装器也是很重要的,在C++11当中是非常夺目耀眼的
Function包装器也叫做适配器,本质上就是一个类模板☞function包装器文档
为什么要使用它呢?
看下面这个例子

#include <functional>
#include <iostream>
using namespace std;
struct Add
{int operator()(int x,int y){return x + y;}
};int add(int x, int y)
{return x + y;
}template<class T>
void Func(T way)
{cout<<way(4,2)<<endl;
}int main()
{//1.使用函数对象Func(Add());//2.使用函数指针Func(add);//3.使用lambdaFunc([](int x, int y) {return x + y; });return 0;
}

虽然能够正常执行,但是其他效率低下,Func模板生成了三份实例,因此我们的function提供了统一的类型

std::function在头文件<functional>
// 类模板原型如下
template <class T> function;     // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;
//模板参数说明:
//Ret: 被调用函数的返回类型
//Args…:被调用函数的形参

使用优化后的代码,如下

#include <functional>
#include <iostream>
using namespace std;
struct Add
{int operator()(int x,int y){return x + y;}
};int add(int x, int y)
{return x + y;
}template<class T>
void Func(T way)
{cout<<way(4,2)<<endl;
}int main()
{//1.使用函数对象function<int(int, int)> f1 = Add();Func(f1);//2.使用函数指针function<int(int, int)> f2 = add;//function有移动构造Func(f2);//3.使用lambdafunction<int(int,int)> f3 = [](int x, int y) {return x + y; };Func(f3);return 0;
}

接下来讲一下对于类的成员函数怎么使用function包装器

#include <iostream>
#include <functional>
using namespace std;
typedef int T;
class Calculator
{
public:static T Add(T x,T y){return x + y;}T Sub(T x, T y){return x - y;}
};int main()
{//对于类成员函数如何使用function如下//处理静态函数//任选其一function<int(int, int)> f1 = Calculator::Add;function<int(int, int)> f2 = &Calculator::Add;cout << f1(1, 2) << endl;cout << f2(1, 2) << endl;//处理类成员函数	function<int(Calculator,int, int)> f3 =&Calculator::Sub;//必须加上&cout<<f3(Calculator(), 1, 2)<<endl;Calculator c;cout << f3(c,1, 2) << endl;//模板类型使用指针,但是不能传输右值对象了,因为右值无法取地址function<int(Calculator*, int, int)> f4 = &Calculator::Sub;//必须加上&cout << f4(&c, 1, 2);return 0;
}

其实function包装器底层也是调用的是operator()方法,对于类的成员函数,function的模板类型用与不用指针的区别不过是调用的时候用不用指针的问题罢了
我们再看一下是否能够修改调用参数的值

#include <iostream>
#include <functional>
using namespace std;
typedef int T;
class Calculator
{
public:static T Add(T x,T y){return x + y;}T Sub(T x, T y){_val = 10;return x - y;}void Try(Calculator& cal){cal._val = 9;}int _val=0;//增加一个成员变量,来看function包装器会不会修改对象的值
};int main()
{//处理类成员函数	function<int(Calculator,int, int)> f3 =&Calculator::Sub;//必须加上&Calculator c;f3(c, 1, 2);cout << c._val << endl;//模板类型使用指针,但是不能传输右值对象了,因为右值无法取地址function<int(Calculator*, int, int)> f4 = &Calculator::Sub;//必须加上&f4(&c, 1, 2);//使用指针就修改了cout << c._val << endl;function<void(Calculator, Calculator&)> f5 = &Calculator::Try;f5(c,c);cout << c._val << endl;return 0;
}

在这里插入图片描述

3.bind

bind是一个函数模板,就像一个函数包装器,接收一个可以调用的对象,生成一个新的可调用对象来适应原对象的参数列表
调用bind的一般形式:auto newCallable=bind(callable,arg_list);
其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数
arg_list中可能包含形如_n的名字,其中n是整数,这些参数是“占位符”,表示newCallable的参数,他们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对象中参数位置,_1为第一个参数,_2为第二个参数,以此类推

// 原型如下:
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
// with return type (2) 
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);

☞bind文档
使用见下面的代码,bind主要用在类的成员函数多一点

#include <functional>
#include <iostream>
using namespace std;
typedef int T;
class Calculator
{
public:static T Add(T x, T y){return x + y;}T Sub(T x, T y){_val = 10;return x - y;}void Try(Calculator& cal){cal._val = 9;}int _val = 0;//增加一个成员变量,来看function包装器会不会修改对象的值
};int main()
{//绑定成员函数//单纯的绑定this//&是必须的,placeholders是std命名空间里的,_1,_2是placeholders命名空间里的function<int(int,int)> f1 = bind(&Calculator::Sub, Calculator(), placeholders::_1, placeholders::_2);cout << f1(19, 31) << endl;//不再需要对象或对象指针//绑定全部参数function<int()> f2 = bind(&Calculator::Sub, Calculator(),19,31);cout << f2() << endl;//bind还有调整参数位置的作用Calculator c;//使用_1,_2改变参数位置//绑定为类对象function<int(int,int)> f3 = bind(&Calculator::Sub,c, placeholders::_2, placeholders::_1);cout << f3(19, 31) << endl;//实际应该为31-19//绑定为类指针function<int(int, int)> f4 = bind(&Calculator::Sub,&c, placeholders::_2, placeholders::_1);cout << f4(19, 31) << endl;//实际应该为31-19return 0;
}

在这里插入图片描述

我们来看一下,绑定的值是否会改变

#include <functional>
#include <iostream>
using namespace std;
typedef int T;
class Calculator
{
public:static T Add(T x, T y){return x + y;}T Sub(T x, T y){_val = 10;return x - y;}void Try(Calculator& cal){cal._val = 9;}int _val = 0;//增加一个成员变量,来看function包装器会不会修改对象的值
};int main()
{Calculator c;//使用_1,_2改变参数位置//绑定为类对象function<int(int, int)> f3 = bind(&Calculator::Sub, c, placeholders::_2, placeholders::_1);//cout << f3(19, 31) << endl;//实际应该为31-19cout << c._val << endl;//不会改变//绑定为类指针function<int(int, int)> f4 = bind(&Calculator::Sub, &c, placeholders::_2, placeholders::_1);//cout << f4(19, 31) << endl;//实际应该为31-19cout << c._val << endl;//不会改变//绑定参数function<void()> f5 = bind(&Calculator::Try, &c,c);f5();cout << c._val<< endl;//不会改变c._val = 0;//不绑定参数function<void(Calculator&)> f6 = bind(&Calculator::Try, &c, placeholders::_1);f6(c);cout << c._val << endl;return 0;
}

在这里插入图片描述
可以发现,绑定注的成员无法改变,但是不绑定的就能改变

🌸🌸C++11(下)的知识大概就讲到这里啦,博主后续会继续更新更多C++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/479911.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【组件封装】uniapp vue3 封装一个自定义下拉刷新组件pullRefresh,带刷新时间和加载动画教程

文章目录 前言一、实现原理二、组件样式和功能设计三、scroll-view 自定义下拉刷新使用回顾相关属性&#xff1a;最终版完整代码&#xff1a; 前言 手把手教你封装一个移动端 自定义下拉刷新组件带更新时间和加载动画&#xff08;PullRefresh&#xff09;&#xff0c;以uniapp …

14、保存与加载PyTorch训练的模型和超参数

文章目录 1. state_dict2. 模型保存3. check_point4. 详细保存5. Docker6. 机器学习常用库 1. state_dict nn.Module 类是所有神经网络构建的基类&#xff0c;即自己构建一个深度神经网络也是需要继承自nn.Module类才行&#xff0c;并且nn.Module中的state_dict包含神经网络中…

【Threejs进阶教程-着色器篇】9.顶点着色器入门

【Threejs进阶教程-着色器篇】9.顶点着色器入门 本系列教程第一篇地址&#xff0c;建议按顺序学习认识顶点着色器varying介绍顶点着色器与片元着色器分别的作用Threejs在Shader中的内置变量各种矩阵gl_Position 尝试使用顶点着色器增加分段数增强效果 制作平面鼓包效果鼓包效果…

w058基于web的美发门店管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0…

leetcode 二叉树的最大深度

104. 二叉树的最大深度 已解答 简单 相关标签 相关企业 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3…

VMware ubuntu创建共享文件夹与Windows互传文件

1.如图1所示&#xff0c;点击虚拟机&#xff0c;点击设置&#xff1b; 图1 2.如图2所示&#xff0c;点击选项&#xff0c;点击共享文件夹&#xff0c;如图3所示&#xff0c;点击总是启用&#xff0c;点击添加&#xff1b; 图2 图3 3.如图4所示&#xff0c;出现命名共享文件夹…

matlab 实现混沌麻雀搜索算法的光伏MPPT控制仿真

1、内容简介 略 103-可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略

Unity3D 截图

使用 Unity3D 自带的截图接口&#xff0c;制作截图工具。 截图 有时候我们想对 Unity 的窗口进行截图&#xff0c;如果直接使用一些截图工具&#xff0c;很难截取到一张完整分辨率的图片&#xff08;例如&#xff0c;我们想要截取一张 1920 * 1080 的图片&#xff09;。 其实…

STM32F10x 定时器

使用定时器实现&#xff1a;B5 E5的开关 添加相关的.h路径文件 添加相关的.c配置文件 led.h文件 用于声明LED函数 #ifndef __LED_H //没有定义__LED_H #define __LED_H //就定义__LED_H #define LED1_ON GPIO_ResetBits(GPIOB,GPIO_Pin_5) #defi…

PMP好考吗,有多大的价值?

非常好考&#xff01;PMP目前大陆地区的笔试是只有选择题的&#xff0c;运气好的话 蒙一个都能对&#xff0c;所以PMP的通过率高&#xff0c;这也是很多人考了吐槽PMP没用&#xff0c;是“水证”&#xff0c;但是每年考PMP 的人不减反增&#xff0c;大家可以想一下&#xff0c;…

css:项目

这是一个完整的网站制作的流程 美工会先制作一个原型图&#xff1a; 原型图写的不详细&#xff0c;就是体现一个网页大致的布局 然后美工再做一个psd样例图片 然后再交给程序员 项目 模块化开发&#xff1a;把代码的不同的样式封装起来&#xff0c;需要用到相同样式的标签就…

VsCode 插件推荐(个人常用)

VsCode 插件推荐&#xff08;个人常用&#xff09;

黑马程序员Java项目实战《苍穹外卖》Day01

苍穹外卖-day01 课程内容 软件开发整体介绍苍穹外卖项目介绍开发环境搭建导入接口文档Swagger 项目整体效果展示&#xff1a; ​ 管理端-外卖商家使用 ​ 用户端-点餐用户使用 当我们完成该项目的学习&#xff0c;可以培养以下能力&#xff1a; 1. 软件开发整体介绍 作为一…

Python双向链表、循环链表、栈

一、双向链表 1.作用 双向链表也叫双面链表。 对于单向链表而言。只能通过头节点或者第一个节点出发&#xff0c;单向的访问后继节点&#xff0c;每个节点只能记录其后继节点的信息&#xff08;位置&#xff09;&#xff0c;不能向前遍历。 所以引入双向链表&#xff0c;双…

k8s网络服务

k8s 中向外界提供服务的几种方法port-forward、NodePort&#xff0c;以及 更加常用的提供服务的资源ingress。 1 kubectl port-forward service/redis 6379:6379 现在k8s中有一个pod运行在6379&#xff0c;本机访问映射到6379上&#xff0c;它可以针对部署&#xff0c;服务&…

eduSRC挖洞思路

声明 学习视频来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…

Leetcode - 周赛424

目录 一&#xff0c;3354. 使数组元素等于零 二&#xff0c; 3355. 零数组变换 I 三&#xff0c;3356. 零数组变换 II 四&#xff0c;3357. 最小化相邻元素的最大差值 一&#xff0c;3354. 使数组元素等于零 本题实际上是一个前/后缀和的问题&#xff0c;就是判断前缀和与后…

Vue2中 vuex 的使用

1.安装 vuex 安装vuex与vue-router类似&#xff0c;vuex是一个独立存在的插件&#xff0c;如果脚手架初始化没有选 vuex&#xff0c;就需要额外安装。 yarn add vuex3 或者 npm i vuex3 233 Vue2 Vue-Router3 Vuex3 344 Vue3 Vue-Router4 Vuex4 2. 新建 store/index.j…

数据结构C语言描述5(图文结合)--队列,数组、链式、优先队列的实现

前言 这个专栏将会用纯C实现常用的数据结构和简单的算法&#xff1b;有C基础即可跟着学习&#xff0c;代码均可运行&#xff1b;准备考研的也可跟着写&#xff0c;个人感觉&#xff0c;如果时间充裕&#xff0c;手写一遍比看书、刷题管用很多&#xff0c;这也是本人采用纯C语言…

Windows修复SSL/TLS协议信息泄露漏洞(CVE-2016-2183) --亲测

漏洞说明&#xff1a; 打开链接&#xff1a;https://docs.microsoft.com/zh-cn/troubleshoot/windows-server/windows-security/restrict-cryptographic-algorithms-protocols-schannel 可以看到&#xff1a; 找到&#xff1a;应通过配置密码套件顺序来控制 TLS/SSL 密码 我们…