C++11 std::function和std::bind

1 可調用對象

不同類型可能有相同的調用形式,如:

// 普通函數
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::funtion可以用同一種方式將上述類型保存起來:

std::function<int(int, int)> a = add;
std::function<int(int, int)> b = mod;
std::function<int(int, int)> c = divide();

2 std::function

std::function是一個可調用對象包裝器,是一個類模板,可以容納除了類成員函數指針之外的所有可調用對象,她可以用統一的方式處理函數、函數指針、函數對象,並能保存和延遲他們的執行。

定義格式std::function<函數類型>。

std::function可以取代函數指針的作用,因爲它可以延遲函數的執行,特別適合作爲回調函數使用。它比普通函數指針更加靈活和便利。

3 std::bind

std::bind將可調用對象與其參數一起進行綁定,綁定後的結果可以使用std::function保存。std::bind主要有以下兩個作用:

  • 將可調用對象和其參數綁定成一個仿函數;
  • 只綁定部分參數,減少可調用對象傳入的參數。

3.1 std::bind綁定普通函數

double my_divide (double x, double y) {return x/y;}
auto fn_half = std::bind (my_divide,_1,2);  
std::cout << fn_half(10) << '\n';
  • bind的第一個參數是函數名,普通函數做實參時,會隱式轉換成函數指針。因此std::bind (my_divide,_1,2)等價於std::bind (&my_divide,_1,2);
  • _1表示佔位符,位於<functional>中,std::placeholders::_1;

3.2 std::bind綁定一個成員函數

struct Foo {
    void print_sum(int n1, int n2)
    {
        std::cout << n1+n2 << '\n';
    }
    int data = 10;
};
int main() 
{
    Foo foo;
    auto f = std::bind(&Foo::print_sum, &foo, 95, std::placeholders::_1);
    f(5); // 100
}
  • bind綁定類成員函數時,第一個參數表示對象的成員函數的指針,第二個參數表示對象的地址。
  • 必須顯示的指定&Foo::print_sum,因爲編譯器不會將對象的成員函數隱式轉換成函數指針,所以必須在Foo::print_sum前添加&;
  • 使用對象成員函數的指針時,必須要知道該指針屬於哪個對象,因此第二個參數爲對象的地址 &foo;

本文參考自:

https://www.jianshu.com/p/f191e88dcc80

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章