欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++異步操作future和aysnc與function和bind

 更新時(shí)間:2022年09月02日 08:29:46   作者:GopherWxf???????  
這篇文章主要介紹了C++異步操作future和aysnc與function和bind,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

異步操作

C++11為異步操作提供了4個(gè)接口

  • std::future : 異步指向某個(gè)任務(wù),然后通過(guò)future特性去獲取任務(wù)函數(shù)的返回結(jié)果。
  • std::aysnc: 異步運(yùn)行某個(gè)任務(wù)函數(shù)。
  • std::packaged_task :將任務(wù)和feature綁定在一起的模板,是一種封裝對(duì)任務(wù)的封裝。
  • std::promise:承諾

std::future和std::aysnc 介紹

std::future期待一個(gè)函數(shù)的返回值,從一個(gè)異步調(diào)用的角度來(lái)說(shuō),future更像是執(zhí)行函數(shù)的返回值,C++標(biāo)準(zhǔn)庫(kù)使用std::future為一次性事件建模,如果一個(gè)事件需要等待特定的一次性事件,那么這線程可以獲取個(gè)future對(duì)象來(lái)代表這個(gè)事件。

異步調(diào)用往往不知道何時(shí)返回,但是如果異步調(diào)用的過(guò)程需要同步,或者說(shuō)后一個(gè)異步調(diào)用需要使用前一個(gè)異步調(diào)用的結(jié)果。這個(gè)時(shí)候就要用到future。也就是說(shuō),可選擇同步,也可選擇異步。

future的表現(xiàn)為期望,當(dāng)前線程持有future時(shí),期望從future獲取到想要的結(jié)果和返回,可以把future當(dāng)做異步函數(shù)的返回值。

線程可以周期性的在這個(gè)future上等待一小段時(shí)間,檢查future是否已經(jīng)ready,如果沒(méi)有,該線程可以先去做另一個(gè)任務(wù),一旦future就緒,該future就無(wú)法復(fù)位(無(wú)法再次使用這個(gè)future等待這個(gè)事件),所以future代表的是一次性事件。

在庫(kù)的頭文件中聲明了兩種future,唯一future(std::future)和共享future(std::shared_future)這兩個(gè)是參照std::unique_ptr和std::shared_ptr設(shè)立的,前者的實(shí)例是僅有的一個(gè)指向其關(guān)聯(lián)事件的實(shí)例,而后者可以有多個(gè)實(shí)例指向同一個(gè)關(guān)聯(lián)事件,當(dāng)事件就緒時(shí),所有指向同一事件的std::shared_future實(shí)例會(huì)變成就緒。

跟thread類(lèi)似,async允許你通過(guò)將額外的參數(shù)添加到調(diào)用中,來(lái)將附加參數(shù)傳遞給函數(shù)。如果傳入的函數(shù)指針是某個(gè)類(lèi)的成員函數(shù),則還需要將類(lèi)對(duì)象指針傳入(直接傳入,傳入指針,或者是std::ref封裝)。

默認(rèn)情況下,std::async是否啟動(dòng)一個(gè)新線程,或者在等待future時(shí),任務(wù)是否同步運(yùn)行都取決于你給的參數(shù)。這個(gè)參數(shù)為std::launch類(lèi)型,async運(yùn)行某個(gè)任務(wù)函數(shù),至于異步運(yùn)行還是同步運(yùn)行,由這個(gè)參數(shù)決定

默認(rèn)選項(xiàng)參數(shù)被設(shè)置為std::launch::any。如果函數(shù)被延遲運(yùn)行可能永遠(yuǎn)都不會(huì)運(yùn)行,因?yàn)楹苡锌赡軐?duì)應(yīng)的future沒(méi)有調(diào)用get。

enum class launch{
	async,deferred,sync=deferred,any=async|deferred
};
  • std::launch::async,表明函數(shù)會(huì)在創(chuàng)建的新線程上運(yùn)行。
  • std::launch::defered表明該函數(shù)會(huì)被延遲調(diào)用,直到在future上調(diào)用get()或者wait()為止。
  • std::launch::sync = std::launch::defered,表明該函數(shù)會(huì)被延遲調(diào)用
  • std::launch::any = std::launch::defered | std::launch::async,表明該函數(shù)會(huì)被延遲調(diào)用,調(diào)用時(shí)在新線程上運(yùn)行。

std::future和std::aysnc的使用Demo

這里我們future了兩個(gè)函數(shù),第一個(gè)函數(shù)設(shè)置為異步,那么在第20行之后,就會(huì)創(chuàng)建一個(gè)新線程并運(yùn)行,而不必等待result.get()。第二個(gè)函數(shù)沒(méi)有設(shè)置參數(shù),那么默認(rèn)是延遲調(diào)用,只有在result2.get()時(shí),才會(huì)創(chuàng)建一個(gè)新線程并運(yùn)行。

#include <iostream>
#include <future>
#include <thread>
using namespace std;
int find_result_to_add() {
	//std::this_thread::sleep_for(std::chrono::seconds(2)); // 用來(lái)測(cè)試異步延遲的影響
	std::cout << "find_result_to_add" << std::endl;
	return 1 + 1;
}
int find_result_to_add2(int a, int b) {
	//std::this_thread::sleep_for(std::chrono::seconds(5)); // 用來(lái)測(cè)試異步延遲的影響
	return a + b;
}
void do_other_things() {
	std::cout << "do_other_things" << std::endl;
	std::this_thread::sleep_for(std::chrono::seconds(5));
}
int main() {
	//async異步 
	std::future<int> result = std::async(std::launch::async,find_result_to_add);
	//std::future<decltype (find_result_to_add())> result = std::async(find_result_to_add);
	//auto result = std::async(find_result_to_add); // 推薦的寫(xiě)法用aoto 

	do_other_things();

	std::cout << "result: " << result.get() << std::endl; // 延遲是否有影響?

	//std::future<decltype (find_result_to_add2(0, 0))> result2 = std::async(find_result_to_add2, 10, 20);
	//不寫(xiě)默認(rèn)any 
	auto result2=std::async(find_result_to_add2, 10, 20);

	std::cout << "result2: " << result2.get() << std::endl; // 延遲是否有影響?

	std::cout << "main finish" << endl;
	return 0;
}

std::packaged_task 介紹

如果說(shuō)std::async和std::feature還是分開(kāi)看的關(guān)系的話,那么std::packaged_task就是將任務(wù)和feature綁定在一起的模板,是一種封裝對(duì)任務(wù)的封裝。

The class template std::packaged_task wraps any Callable target (function, lambda expression, bind expression, or another function object) so that it can be invoked asynchronously. Its return value or exception thrown is stored in a shared state which can be accessed through std::future objects.

可以通過(guò)std::packaged_task對(duì)象獲取任務(wù)相關(guān)聯(lián)的feature,調(diào)用get_future()方法可以獲得std::packaged_task對(duì)象綁定的函數(shù)的返回值類(lèi)型的future。std::packaged_task的模板參數(shù)是函數(shù)簽名。( 例如int add(int a, intb)的函數(shù)簽名就是int(int, int) )

std::packaged_task的使用Demo

#include <iostream>
#include <future>
using namespace std;
int add(int a, int b, int c) {
	std::cout << "call add\n";
	return a + b + c;
}
void do_other_things() {
	std::cout << "do_other_things" << std::endl;
}
int main() {
	std::packaged_task<int(int, int, int)> task(add); // 封裝任務(wù)
	do_other_things();
	std::future<int> result = task.get_future();
	task(1, 1, 2); //必須要讓任務(wù)執(zhí)行,否則在get()獲取future的值時(shí)會(huì)一直阻塞
	std::cout << "result:" << result.get() << std::endl;
	return 0;
}

std::promise 的介紹

std::promise提供了一種設(shè)置值的方式,它可以在這之后通過(guò)相關(guān)聯(lián)的std::future對(duì)象進(jìn)行讀取。換種說(shuō)法,之前已經(jīng)說(shuō)過(guò)std::future可以讀取一個(gè)異步函數(shù)的返回值了,那么這個(gè)std::promise就提供一種方式手動(dòng)讓future就緒

出在promise創(chuàng)建好的時(shí)候future也已經(jīng)創(chuàng)建好了,線程在創(chuàng)建promise的同時(shí)會(huì)獲得一個(gè)future,然后將promise傳遞給設(shè)置他的線程,當(dāng)前線程則持有future,以便隨時(shí)檢查是否可以取值。

promise是一個(gè)承諾,當(dāng)線程創(chuàng)建了promise對(duì)象后,這個(gè)promise對(duì)象向線程承諾他必定會(huì)被人設(shè)置一個(gè)值,和promise相關(guān)聯(lián)的future就是獲取其返回的手段。

std::promise的使用Demo

#include <future>
#include <string>
#include <thread>
#include <iostream>
using namespace std;
void print(std::promise<std::string>& p) {
	p.set_value("There is the result whitch you want.");
}
void do_some_other_things() {
	std::cout << "Hello World" << std::endl;
}
int main() {
	std::promise<std::string> promise;
	std::future<std::string> result = promise.get_future();

	std::thread th(print, std::ref(promise));

	do_some_other_things();
	std::cout << result.get() << std::endl;

	th.join();
	return 0;
}

function和bind

在設(shè)計(jì)回調(diào)函數(shù)的時(shí)候,無(wú)可避免地會(huì)接觸到可回調(diào)對(duì)象。在C++11中,提供了std::function和std::bind兩個(gè)方法來(lái)對(duì)可回調(diào)對(duì)象進(jìn)行統(tǒng)一和封裝。(回調(diào)函數(shù)就是一個(gè)被作為參數(shù)傳遞的函數(shù))

C++語(yǔ)言中有幾種可調(diào)用對(duì)象:函數(shù)、函數(shù)指針、lambda表達(dá)式、bind創(chuàng)建的對(duì)象以及重載了函數(shù)調(diào)用運(yùn)算符的類(lèi)。和其他對(duì)象一樣,可調(diào)用對(duì)象也有類(lèi)型。例如,每個(gè)lambda有它自己唯一的(未命名)類(lèi)類(lèi)型;函數(shù)及函數(shù)指針的類(lèi)型則由其返回值類(lèi)型和實(shí)參類(lèi)型決定。

function的用法

頭文件:#include <functional>

  • 保存普通函數(shù)
//保存普通函數(shù)
void func1(int a) {
	cout << a << endl;
}
//1. 保存普通函數(shù)
std::function<void(int a)> func1_;
func1_ = func1;
func1_(2); //2
  • 保存lambda表達(dá)式
//2. 保存lambda表達(dá)式
std::function<void()> func2_ = []() {
	cout << "hello lambda" << endl;
};
func2_(); //hello world
  • 保存成員函數(shù)
//保存成員函數(shù)
class A {
	public:
		A(string name) : name_(name) {}
		void func3(int i) const {
			cout <<name_ << ", " << i << endl;
		}
	private:
		string name_;
};

//3 保存成員函數(shù)
	std::function<void(const A&,int)> func3_ = &A::func3;
	A a("wxf");
	func3_(a, 20);

完整代碼:

#include <iostream>
#include <functional>
using namespace std;
//保存普通函數(shù)
void func1(int a) {
	cout << a << endl;
}
//保存成員函數(shù)
class A {
	public:
		A(string name) : name_(name) {}
		void func3(int i) const {
			cout <<name_ << ", " << i << endl;
		}
	private:
		string name_;
};
int main() {
	cout << "main1 -----------------" << endl;
	//1. 保存普通函數(shù)
	std::function<void(int a)> func1_;
	func1_ = func1;
	func1_(2); //2

	cout << "\n\nmain2 -----------------" << endl;
	//2. 保存lambda表達(dá)式
	std::function<void()> func2_ = []() {
		cout << "hello lambda" << endl;
	};
	func2_(); //hello world

	cout << "\n\nmain3 -----------------" << endl;
	//3 保存成員函數(shù)
	std::function<void(const A&,int)> func3_ = &A::func3;
	A a("wxf");
	func3_(a, 20);
	return 0;
}
main1 -----------------
2
main2 -----------------
hello lambda
main3 -----------------
wxf, 20

bind的用法

可將bind函數(shù)看作是一個(gè)通用的函數(shù)適配器,它接受一個(gè)可調(diào)用對(duì)象,生成一個(gè)新的可調(diào)用對(duì)象來(lái)“適應(yīng)”原對(duì)象的參數(shù)列表。調(diào)用bind的一般形式:auto newCallable = bind(callable, arg_list);

其中,newCallable本身是一個(gè)可調(diào)用對(duì)象,arg_list是一個(gè)逗號(hào)分隔的參數(shù)列表,對(duì)應(yīng)給定的callable的參數(shù)。即,當(dāng)我們調(diào)用newCallable時(shí),newCallable會(huì)調(diào)用callable,并傳給它arg_list中的參數(shù)。

arg_list中的參數(shù)可能包含形如placeholders::_n的名字,其中n是一個(gè)整數(shù),這些參數(shù)是“占位符”,表示newCallable的參數(shù),它們占據(jù)了傳遞給newCallable的參數(shù)的“位置”。數(shù)值n表示生成的可調(diào)用對(duì)象中參數(shù)的位置:placeholders::_1為newCallable的第一個(gè)參數(shù),placeholders::_2為第二個(gè)參數(shù),以此類(lèi)推。

可能看描述還不是很懂,下面來(lái)看看代碼:

#include <iostream>
#include <functional>
using namespace std;

void fun_1(int x,int y,int z) {
	cout<<"fun_1 print unchanged: x=" <<x<<",y="<< y << ",z=" <<z<<endl;
}
void fun_2(int &a,int &b) {
	a++;
	b++;
	cout<<"fun_2 print Increment: a=" <<a<<",b="<<b<<endl;
}
class A {
	public:
		// 重載fun_3,主要bind的時(shí)候需要
		// std::bind((void(A::*)(int, int))&A::fun_3
		void fun_3(int k,int m) {
			cout << "fun_3 a = " << a << cout <<"\t print unchanged: k="<<k<<",m="<<m<<endl;
		}
		// std::bind((void(A::*)(string))&A::fun_3
		void fun_3(string str) {
			cout<<"fun_3 print: str="<<str<<endl;
		}
		int a;
};
int main() {
	//f1的類(lèi)型為 function<void(int, int, int)>
	cout << "\n\nstd::bind(fun_1, 1, 2, 3) -----------------\n";
	auto f1 = std::bind(fun_1, 1, 2, 3); //表示綁定函數(shù) fun 的第一,二,三個(gè)參數(shù)值為:1 2 3
	f1(); //print: x=1,y=2,z=3

	cout << "\n\nstd::bind(fun_1, 10, 20, 30) -----------------\n";
	auto f1_1 = std::bind(fun_1, 10, 20, 30); //表示綁定函數(shù) fun 的第一,二,三個(gè)參數(shù)值為: 1 2 3
	f1_1();

	cout << "\n\nstd::bind(fun_1, placeholders::_1,placeholders::_2, 3) -----------------\n";
	auto f2 = std::bind(fun_1, placeholders::_1, placeholders::_2, 3);
	//表示綁定函數(shù) fun_1的第三個(gè)參數(shù)為 3,而fun_1的第一,二個(gè)參數(shù)分別由調(diào)用 f2 的第一,二個(gè)參數(shù)指定
	f2(1,2);//print: x=1,y=2,z=3
	f2(10,21,30); // 傳入30也沒(méi)有用

	cout << "\n\nstd::bind(fun_1,placeholders::_2,placeholders::_1,3) -----------------\n";
	auto f3 = std::bind(fun_1,placeholders::_2,placeholders::_1,3);
	//表示綁定函數(shù) fun_1 的第三個(gè)參數(shù)為 3,而fun_1的第一,二個(gè)參數(shù)分別由調(diào)用 f3 的第二,一個(gè)參數(shù)指定
	//注意: f2 和 f3 的區(qū)別。
	f3(1,2);//print: x=2,y=1,z=3

	cout << "\n\nstd::bind(fun_2, placeholders::_1, n) -----------------\n";
	int m = 2;
	int n = 3;
	////表示綁定fun_2的第一個(gè)參數(shù)為n, fun_2的第二個(gè)參數(shù)由調(diào)用f4的第一個(gè)參數(shù)(_1)指定。
	auto f4 = std::bind(fun_2, placeholders::_1, n); //func_2(3,<f4_1>)
	f4(m); //print: m=3,n=4
	cout<<"m="<<m<<endl;//m=3 說(shuō)明:bind對(duì)于不事先綁定的參數(shù),通過(guò)std::placeholders傳遞的參數(shù)是通過(guò)引用傳遞的,如m
	cout<<"n="<<n<<endl;//n=3 說(shuō)明:bind對(duì)于預(yù)先綁定的函數(shù)參數(shù)是通過(guò)值傳遞的,如n

	cout << "\n\nstd::bind(&A::fun_3,&a1,40,50) -----------------\n";
	A a;
	a.a = 10;
	//f5的類(lèi)型為 function<void(int, int)>
	auto f5 = std::bind((void(A::*)(int, int))A::fun_3, &a, 40, 50); 
	f5(10,20);//參數(shù)以及寫(xiě)死,傳參沒(méi)用 

	cout << "\n\nstd::bind(&A::fun_3, &a2,placeholders::_1,placeholders::_2) -----------------\n";
	A a2;
	a2.a = 20;
	//f5的類(lèi)型為 function<void(int, int)>
	auto f6 = std::bind((void(A::*)(int, int))&A::fun_3,&a2,placeholders::_1,placeholders::_2); //使用auto關(guān)鍵字
	f6(10,20);//調(diào)用a.fun_3(10,20),print: k=10,m=20

	cout << "\n\nstd::bind(&A::fun_3,a3,std::placeholders::_1,std::placeholders::_2) -----------------\n";
	std::function<void(int,int)> fc = std::bind((void(A::*)(int,int))&A::fun_3, &a,std::placeholders::_1,std::placeholders::_2);
	fc(10,20); //調(diào)用a.fun_3(10,20) print: k=10,m=20
	fc = std::bind((void(A::*)(int, int))&A::fun_3,&a2,std::placeholders::_1,std::placeholders::_2);

	cout << "\n\nstd::bind(&A::fun_3,&a1,std::placeholders::_1) -----------------\n";
	auto f_str = std::bind((void(A::*)(string))&A::fun_3,a,std::placeholders::_1);
	f_str("wxf");

	return 0;
}

到此這篇關(guān)于C++異步操作future和aysnc與function和bind的文章就介紹到這了,更多相關(guān)C++異步操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++ boost::asio編程-同步TCP詳解及實(shí)例代碼

    C++ boost::asio編程-同步TCP詳解及實(shí)例代碼

    這篇文章主要介紹了C++ boost::asio編程-同步TCP詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • C++ LeetCode1781題解所有子字符串美麗值之和

    C++ LeetCode1781題解所有子字符串美麗值之和

    這篇文章主要為大家介紹了C++ LeetCode1781題解所有子字符串美麗值之和,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • C++賦值運(yùn)算符

    C++賦值運(yùn)算符

    這篇文章主要介紹了C++賦值運(yùn)算符,C++當(dāng)中允許類(lèi)對(duì)象賦值,這是通過(guò)默認(rèn)的重載賦值運(yùn)算符實(shí)現(xiàn)的,下面我們就來(lái)介紹介紹該內(nèi)容吧,,需要的朋友可以參考一下
    2022-01-01
  • QT?.pro文件使用解析

    QT?.pro文件使用解析

    QT工程的pro文件,在創(chuàng)建工程時(shí)由QTCreater自動(dòng)創(chuàng)建,我們可以往里面添加內(nèi)容,增加庫(kù)文件的聲明,包含路徑、預(yù)處理器定義,生成目錄,輸出中間目錄等等設(shè)置,本文就來(lái)介紹一下
    2022-04-04
  • C++實(shí)現(xiàn)簡(jiǎn)單職工信息管理系統(tǒng)

    C++實(shí)現(xiàn)簡(jiǎn)單職工信息管理系統(tǒng)

    本文給大家分享的是使用C++實(shí)現(xiàn)簡(jiǎn)單的職工信息管理系統(tǒng)的代碼,本系統(tǒng)采用了面向?qū)ο蟮某绦蛟O(shè)計(jì)方法,所有的方法均以類(lèi)為基礎(chǔ),感興趣的小伙伴們可以參考一下
    2015-08-08
  • C++?雙冒號(hào)::符號(hào)詳解

    C++?雙冒號(hào)::符號(hào)詳解

    本文主要介紹了C++?雙冒號(hào)::符號(hào)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • C++深入講解哈夫曼樹(shù)

    C++深入講解哈夫曼樹(shù)

    給定N個(gè)權(quán)值作為N個(gè)葉子結(jié)點(diǎn),構(gòu)造一棵二叉樹(shù),若該樹(shù)的帶權(quán)路徑長(zhǎng)度達(dá)到最小,稱(chēng)這樣的二叉樹(shù)為最優(yōu)二叉樹(shù),也稱(chēng)為哈夫曼樹(shù)(Huffman Tree)。哈夫曼樹(shù)是帶權(quán)路徑長(zhǎng)度最短的樹(shù),權(quán)值較大的結(jié)點(diǎn)離根較近
    2022-05-05
  • C++簡(jiǎn)單又輕松的講解類(lèi)和對(duì)象中友元函數(shù)

    C++簡(jiǎn)單又輕松的講解類(lèi)和對(duì)象中友元函數(shù)

    采用類(lèi)的機(jī)制后實(shí)現(xiàn)了數(shù)據(jù)的隱藏與封裝,類(lèi)的數(shù)據(jù)成員一般定義為私有成員,成員函數(shù)一般定義為公有的,依此提供類(lèi)與外界間的通信接口。但是,有時(shí)需要定義一些函數(shù),這些函數(shù)不是類(lèi)的一部分,但又需要頻繁地訪問(wèn)類(lèi)的數(shù)據(jù)成員,這時(shí)可以將這些函數(shù)定義為該類(lèi)的友元函數(shù)
    2022-06-06
  • 最小生成樹(shù)算法C語(yǔ)言代碼實(shí)例

    最小生成樹(shù)算法C語(yǔ)言代碼實(shí)例

    這篇文章主要介紹了最小生成樹(shù)算法C語(yǔ)言代碼實(shí)例,有需要的朋友可以參考一下
    2013-12-12
  • C語(yǔ)言詳細(xì)講解strcpy strcat strcmp函數(shù)的模擬實(shí)現(xiàn)

    C語(yǔ)言詳細(xì)講解strcpy strcat strcmp函數(shù)的模擬實(shí)現(xiàn)

    這篇文章主要介紹了怎樣用C語(yǔ)言模擬實(shí)現(xiàn)strcpy與strcat和strcmp函數(shù),strcpy()函數(shù)是C語(yǔ)言中的一個(gè)復(fù)制字符串的庫(kù)函數(shù),strcat()函數(shù)的功能是實(shí)現(xiàn)字符串的拼接,strcmp()函數(shù)作用是比較字符串str1和str2是否相同
    2022-05-05

最新評(píng)論