2014-12-05 62 views
5

我正在學習C++ Boost庫的asio編程。而且我遇到了很多使用函數bind()的函數,它有函數指針作爲參數。函數綁定的目的

我一直無法理解bind()函數的用法。這就是爲什麼我難以理解使用boost庫的asio的程序。

我不想在這裏尋找任何代碼。我只想知道bind()函數或其任何等價函數的用法。 在此先感謝。

+1

它將一個函數轉換爲另一個函數,其中一個或多個(或零個)參數是固定的。例如,f(x,y)→f(5,y)。 – Noel 2014-12-05 11:37:16

+0

對不起,但我沒有讓你很好。 – 2014-12-05 11:39:10

+0

可能有所幫助:http://www.codeproject.com/Articles/13015/A-look-at-the-Boost-Bind-and-Function-libraries – midor 2014-12-05 12:55:57

回答

4

cppreference

函數模板綁定生成對於f轉發呼叫包裝。 調用這個包裝器相當於調用f,其中一些 參數綁定到args。

檢查example below展示綁定

#include <iostream> 
#include <functional> 

using namespace std; 

int my_f(int a, int b) 
{ 
    return 2 * a + b; 
} 

int main() 
{ 
    using namespace std::placeholders; // for _1, _2, _3... 

    // Invert the order of arguments 
    auto my_f_inv = bind(my_f, _2, _1);  // 2 args b and a 
    // Fix first argument as 10 
    auto my_f_1_10 = bind(my_f, 10, _1);  // 1 arg b 
    // Fix second argument as 10 
    auto my_f_2_10 = bind(my_f, _1, 10);  // 1 arg a 
    // Fix both arguments as 10 
    auto my_f_both_10 = bind(my_f, 10, 10);  // no args 

    cout << my_f(5, 15) << endl; // expect 25 
    cout << my_f_inv(5, 15) << endl; // expect 35 
    cout << my_f_1_10(5) << endl; // expect 25 
    cout << my_f_2_10(5) << endl; // expect 20 
    cout << my_f_both_10() << endl; // expect 30 

    return 0; 
} 

可以使用綁定操作現有的函數的參數順序,或修復一些參數。這可以在stl容器和算法中特別有用,您可以在其中傳遞簽名與您的需求相匹配的現有庫函數。

例如,如果你想在集裝箱改造所有的雙打功率2,你可以簡單地傳遞這樣做std::transform(begin(dbl_vec), end(dbl_vec), begin(dbl_vec), std::bind(std::pow, _1, 2))

Live example here

2

您發佈到boost::asio服務的任務必須是可調用的,其參數爲零,以便服務可以存儲它們並在擁有備用資源(即空閒線程)後調用它們。假設你想要它調用函數void purr(int kitty),爲了給這個服務一個格式,它可以與你需要的綁定kitty參數給purr函數。這會給你一個對象,這個對象可以用()沒有任何你可以提供給服務的參數。

當然,使用C++ 11和lambda函數現在最好的方法是做io_service.post([&](){ purr(3); });並避免使用bind

1

它可以讓你聯想(或「綁定」)你使用您希望庫調用的函數自己的數據,而無需庫知道有關數據的任何信息。

既然你在看Boost.Asio,看看他們的tutorial for binding arguments to a handler。他們有他們想要的處理程序,它需要指向自己的數據,定時器本身和計數器使用功能:

void print(const boost::system::error_code& /*e*/, 
    boost::asio::deadline_timer* t, int* count) 
{ 
    // ... 
} 

計時器的async_wait功能使用戶提供的函數被調用時,定時器到期;但只提供了這些論點中的第一個。該處理器是形式的

void handler(
    const boost::system::error_code& error // Result of operation. 
); 

所以我們可以使用bind其他兩個要傳遞我們的函數(希望三個參數)變換成一個只想要一個說法,通過指定的值:

t.async_wait(boost::bind(print, 
    boost::asio::placeholders::error, &t, &count)); 

bind的結果是一個函數對象(即一個類型的對象,它重載函數調用操作符operator()),在這種情況下,它只接受一個參數。參數placeholders::error表示第一個參數仍然是新函數類型的參數;當調用新函數時,另外兩個參數的值爲&t&count。所以,如果我們這個稱自己爲:

auto f = boost::bind(print, boost::asio::placeholders::error, &t, &count) 
f(some_error); 

這個本來是調用原有的功能與參數相同的效果:

print(some_error, &t, &count); 

現在,當計時器到期時,我們的函數被調用,與我們提供的論點,沒有Asio圖書館需要知道他們的任何事情。