C++笔记--std::相关
std::packaged_task
https://www.cnblogs.com/haippy/p/3279565.html
https://en.cppreference.com/w/cpp/thread/packaged_task
std::packaged_task 包装一个可调用的对象,并且允许异步获取该可调用对象产生的结果,从包装可调用对象意义上来讲,std::packaged_task 与 std::function 类似,只不过 std::packaged_task 将其包装的可调用对象的执行结果传递给一个 std::future 对象(该对象通常在另外一个线程中获取 std::packaged_task 任务的执行结果)。
std::packaged_task 对象内部包含了两个最基本元素,一、被包装的任务(stored task),任务(task)是一个可调用的对象,如函数指针、成员函数指针或者函数对象,二、共享状态(shared state),用于保存任务的返回值,可以通过 std::future 对象来达到异步访问共享状态的效果。
可以通过 std::packged_task::get_future 来获取与共享状态相关联的 std::future 对象。在调用该函数之后,两个对象共享相同的共享状态,具体解释如下:
- std::packaged_task 对象是异步 Provider,它在某一时刻通过调用被包装的任务来设置共享状态的值。
- std::future 对象是一个异步返回对象,通过它可以获得共享状态的值,当然在必要的时候需要等待共享状态标志变为 ready.
#include <iostream> // std::cout
#include <utility> // std::move
#include <future> // std::packaged_task, std::future
#include <thread> // std::thread int main ()
{
std::packaged_task<int(int)> foo; // 默认构造函数. // 使用 lambda 表达式初始化一个 packaged_task 对象.
std::packaged_task<int(int)> bar([](int x){return x*;}); foo = std::move(bar); // move-赋值操作,也是 C++11 中的新特性. // 获取与 packaged_task 共享状态相关联的 future 对象.
std::future<int> ret = foo.get_future(); std::thread(std::move(foo), ).detach(); // 产生线程,调用被包装的任务. int value = ret.get(); // 等待任务完成并获取结果.
std::cout << "The double of 10 is " << value << ".\n"; return ;
}
#include <iostream>
#include <cmath>
#include <thread>
#include <future>
#include <functional> // unique function to avoid disambiguating the std::pow overload set
int f(int x, int y) { return std::pow(x,y); } void task_lambda()
{
std::packaged_task<int(int,int)> task([](int a, int b) {
return std::pow(a, b);
});
std::future<int> result = task.get_future(); task(, ); std::cout << "task_lambda:\t" << result.get() << '\n';
} void task_bind()
{
std::packaged_task<int()> task(std::bind(f, , ));
std::future<int> result = task.get_future(); task(); std::cout << "task_bind:\t" << result.get() << '\n';
} void task_thread()
{
std::packaged_task<int(int,int)> task(f);
std::future<int> result = task.get_future(); std::thread task_td(std::move(task), , );
task_td.join(); std::cout << "task_thread:\t" << result.get() << '\n';
} int main()
{
task_lambda();
task_bind();
task_thread();
} /*
输出结果
task_lambda: 512
task_bind: 2048
task_thread: 1024
*/
std::remove_reference
https://en.cppreference.com/w/cpp/types/remove_reference
If the type T
is a reference type, provides the member typedef type
which is the type referred to by T
. Otherwise type
is T
.
std::move和std::forward
不错,可以仔细看看: https://www.jianshu.com/p/b90d1091a4ff
https://www.cnblogs.com/boydfd/p/5182743.html
std::function和std::bind
https://www.jianshu.com/p/f191e88dcc80
https://blog.csdn.net/zzhongcy/article/details/88018204
std::function
- std::function 是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。
- 定义格式:std::function<函数类型>。
- std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数指针更加的灵活和便利。
//不同类型可能具有相同的调用形式,如:
// 普通函数
int add(int a, int b){return a+b;} // lambda表达式
auto mod = [](int a, int b){ return a % b;} // 函数对象类
struct divide{
int operator()(int denominator, int divisor){
return denominator/divisor;
}
}; //上述三种可调用对象虽然类型不同,但是共享了一种调用形式:
int(int ,int) //std::function就可以将上述类型保存起来,如下:
std::function<int(int ,int)> a = add;
std::function<int(int ,int)> b = mod ;
std::function<int(int ,int)> c = divide();
std::bind
可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:
- 将可调用对象和其参数绑定成一个防函数;
- 只绑定部分参数,减少可调用对象传入的参数。
绑定普通函数:
double my_divide (double x, double y) {return x/y;}
auto fn_half = std::bind (my_divide,_1,);
std::cout << fn_half() << '\n'; // /*
bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind (my_divide,_1,2)等价于std::bind (&my_divide,_1,2);
_1表示占位符,位于<functional>中,std::placeholders::_1;
*/
绑定成员函数:
/*
bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。
必须显示的指定&Foo::print_sum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::print_sum前添加&;
使用对象成员函数的指针时,必须要知道该指针属于哪个对象,因此第二个参数为对象的地址 &foo;
*/
struct Foo {
void print_sum(int n1, int n2)
{
std::cout << n1+n2 << '\n';
}
int data = ;
};
int main()
{
Foo foo;
auto f = std::bind(&Foo::print_sum, &foo, , std::placeholders::_1);
f(); //
}
std::rec和std::cref
https://blog.csdn.net/lmb1612977696/article/details/81543802
http://www.cnblogs.com/jiayayao/p/6527713.html
C++本身有引用(&),为什么C++11又引入了std::ref?
主要是考虑函数式编程(如std::bind)在使用时,是对参数直接拷贝,而不是引用。
#include <functional>
#include <iostream> void f(int& n1, int& n2, const int& n3)
{
std::cout << "In function: n1[" << n1 << "] n2[" << n2 << "] n3[" << n3 << "]" << std::endl;
++n1; // 增加存储于函数对象的 n1 副本
++n2; // 增加 main() 的 n2
//++n3; // 编译错误
std::cout << "In function end: n1[" << n1 << "] n2[" << n2 << "] n3[" << n3 << "]" << std::endl;
} int main()
{
int n1 = , n2 = , n3 = ;
std::cout << "Before function: n1[" << n1 << "] n2[" << n2 << "] n3[" << n3 << "]" << std::endl;
std::function<void()> bound_f = std::bind(f, n1, std::ref(n2), std::cref(n3));
bound_f();
std::cout << "After function: n1[" << n1 << "] n2[" << n2 << "] n3[" << n3 << "]" << std::endl;
}
std::result_of
https://zh.cppreference.com/w/cpp/types/result_of
它可以在编译的时候推导出一个函数表达式的返回值类型
#include <type_traits>
#include <iostream> struct S {
double operator()(char, int&);
float operator()(int) { return 1.0;}
}; template<class T>
typename std::result_of<T(int)>::type f(T& t)
{
std::cout << "overload of f for callable T\n";
return t();
} template<class T, class U>
int f(U u)
{
std::cout << "overload of f for non-callable T\n";
return u;
} int main()
{
// 以 char 和 int 参数调用 S 的结果是 double
std::result_of<S(char, int&)>::type d = 3.14; // d 拥有 double 类型
static_assert(std::is_same<decltype(d), double>::value, ""); // 以 int 参数调用 S 的结果是 float
std::result_of<S(int)>::type x = 3.14; // x 拥有 float 类型
static_assert(std::is_same<decltype(x), float>::value, ""); // result_of 能以指向成员函数的指针以如下方式使用
struct C { double Func(char, int&); };
std::result_of<decltype(&C::Func)(C, char, int&)>::type g = 3.14;
static_assert(std::is_same<decltype(g), double>::value, ""); f<C>(); // C++11 中可能编译失败; C++14 中调用不可调用重载
}
C++笔记--std::相关的更多相关文章
- MySQL学习笔记-事务相关话题
事务机制 事务(Transaction)是数据库区别于文件系统的重要特性之一.事务会把数据库从一种一致状态转换为另一个种一致状态.在数据库提交工作时,可以确保其要么所有修改都已经保存了,要么所有修改都 ...
- C++11 学习笔记 std::function和bind绑定器
C++11 学习笔记 std::function和bind绑定器 一.std::function C++中的可调用对象虽然具有比较统一操作形式(除了类成员指针之外,都是后面加括号进行调用),但定义方法 ...
- Linux系列笔记 - vim相关记录
一.常用到的vim命令 这里只简单记录常用到的命令,后面会有自己记录的命令,但有些可能不常用. 常规模式: gg 跳到文件头 shift+g 跳到文件尾 行数+gg 跳到指定行 如:123gg 跳到1 ...
- 工作笔记6-java相关
1.有时候安装失败或者要装新版本的JDK,可先卸载JDK: a. 首先执行命令查看服务器下的JDK的版本:命令如下:rpm -qa |grep jdk b. 然后执行命令:yum -y rem ...
- HTTP笔记01-http相关的基础知识
这个系列文章是阅读<图解HTTP>后写下的笔记 当我们在浏览器输入url,点击回车后,浏览器显示我们需要的web页面,那么,这个界面是如何产生的? 根据浏览器地址中输入的url,浏览器从相 ...
- MVC笔记 Controller相关技术
一.Controller的责任 MVC的核心就是Controller(控制器),它负责处理浏览器传送过来的所有请求,并决定要将什么内容响应给浏览器.但Controller并不负责决定内容应该如何显示, ...
- Linux 路由 学习笔记 之一 相关的数据结构
http://blog.csdn.net/lickylin/article/details/38326719 从现在开始学习路由相关的代码,在分析代码之前, 我们还是先分析数据结构,把数据结构之间的关 ...
- C#图解教程学习笔记——类相关的概念
一.一些基本概念1. 字段:隶属于类的变量,即类的成员变量.2. 方法:隶属于类的函数,即类的成员函数.3. 实例成员:类的每个实例拥有自己的各个类成员的副本,这些成员称为实例成员. 改变一个实例字段 ...
- golang学习笔记 go 相关命令
go build 命令一些可选项的用途和用法 在运行go build命令的时候,默认不会编译目标代码包所依赖的那些代码包.当然,如果被依赖的代码包的归档文件(*.a)不存在,或者源码文件有了变化,那么 ...
随机推荐
- 为 docker 中的 nginx 配置 https
没有 https 加持的网站会逐渐地被浏览器标记为不安全的,所以为网站添加 https 已经变得刻不容缓.对于商业网站来说,花钱购买 SSL/TLS 证书并不是什么问题.但对于个人用户来说,如果能有免 ...
- 【Zabbix】Zabbix-agent自动化脚本
zabbix-agent自动化脚本 作用:批量部署zabbix-agent.用于上百台虚拟机都可以被Zabbix监控. 脚本名:inst-agent.sh #!/bin/bash echo " ...
- Docker入门(一)用hello world入门docker
初识Docker Docker是什么? Docker 是一个开源的应用容器引擎,基于 Go 语言并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量 ...
- Hibernate框架笔记01_环境搭建_API_CRUD
目录 1. Hibernate框架的概述 1.1 什么是框架 1.2 经典三层架构 1.3 Hibernate框架 2 Hibernate入门 2.1 下载Hibernate的开发包 2.2 创建项目 ...
- C++系列总结——构造与析构
前言 在使用资源前,我们需要做一些准备工作保证资源能正常使用,在使用完资源后,我们需要做一些扫尾工作保证资源没有泄露,这就是构造与析构了,这和编程语言是无关的,而是使用资源的一种方式.C++只不过是把 ...
- LeetCode 178. 分数排名
1.题目描述 编写一个 SQL 查询来实现分数排名.如果两个分数相同,则两个分数排名(Rank)相同.请注意,平分后的下一个名次应该是下一个连续的整数值.换句话说,名次之间不应该有“间隔”. +--- ...
- vue 音乐App QQ音乐搜索列表最新接口跨域设置
在 webpack.dev.config.js中 'use strict' const utils = require('./utils') const webpack = require('webp ...
- html初步学习
①:<meta name="viewport" content="initial-scale=1.0,maximum-scale=1.0,minimum-scale ...
- angular打包后路由和文件路径不对
base href换成如下script标签 <!-- <base href="/"> --> <script> document.write(' ...
- (最详细)小米MIX的Usb调试模式在哪里打开的教程
当我们使用安卓手机链接pc的时候,或者使用的有些应用比如我们团队营销团队当使用的应用引号精灵,以前老版本就需要开启Usb调试模式下使用,现当新版本不需要了,如果手机没有开启Usb调试模式,pc则没法成 ...