C++11的bind函數


參數綁定

如果一個函數只在一兩個地方操作,使用Lambad很方便,如果在很多地方操作,編寫多次相同的Lambda函數就很不方便,需要定義函數。但是,定義的函數又不能完全代替能捕捉局部變量的Lambda函數,所以就出現了bind函數。
bind函數是C++11標准庫的函數,需要添加頭文件(g++下加-std=c++11)

#include <functional>

bind就是一個通用的函數適配器,它可以接受一個可調用函數,生成一個新的可調用對象來“適應”原函數的參數列表。

std::bind函數

調用bind函數的方式為:

auto newCallable = bind(callable, arg_list);

說明:
callable : 本身就是一個可調用的函數
arg_list : 用逗號分割的參數列表,對應給定的callable參數

當我們調用newCallable時,會調用callable函數,並且將arg_list的參數傳遞給callable函數。

參數占位符

arg_list中有許多占位符,形如_n的名字,其中n是一個整數,表示newCallable的參數的位置比如:_1為newCallable的第一個參數,_2為第二個參數...。

舉例說明:
現在有一個函數:

bool checkSize(const string &s, string::size_type sz)
{
    return s.size() >= sz;
}

使用bind生成一個調用checkSize的對象:

auto check = bind(checkSize, _1, 6);

其中的_1表示需要給第一個參數傳遞一個const string&。

string s = "hello";
bool b1 = check(s); //check(s) 會調用checkSize(s, 6)

使用bind,可以將原來的基於Lambda的find_if調用:

auto wc = find_if(words.begin(), words.end(), [sz](const string &a));

改變為使用checkSize版本:

auto wc = find_if(words.begin(), words.end(), bind(check_size, _1, sz));

_n參數說明

\_n參數都定義在一個名字為placeholders命名空間中,這個命名空間又在std命名空間中。那么\_1就是:

using std::placeholders::_1;

對每一個占位符都要使用using聲明,非常麻煩,可以使用:

using namespace std::placeholders;

placeholders的明明空間也定義在functional.h頭文件中

bind的參數順序

bind綁定的給定函數的參數的順序。比如func是一個函數,它有5個參數,下面對bind的調用:

auto g = bind(fun, a, b, _2, c, _1);

生成一個新的可調用對象,有兩個占位符,傳遞給g的第一個參數綁定到_1,第二個參數綁定到_2,bind調用會將g(_1, _2)映射為f(a, b, _2, c, _1),如:調用g(X, Y)就會調用f(a, b, Y, c, X);

綁定引用參數

默認情況下,bind的非占位符的參數是拷貝到bind返回的可調用的函數中,與Lambda類似,有時候綁定的參數希望用引用的方式傳遞,或不讓綁定的參數類型拷貝。
例如:

for_each(words.begin(), words.end(), [&os, c](const string &s) {os << s << c;});

可以編寫一個函數完成同樣的功能:

ostream &print(ostream &os, const strint &s, char c)
{
    return os << s << c;
}

但是:不能直接用bind來代替os的捕獲:

for_each(words.begin(), words.end(), bind(print, os, _1, ' ');

由於不能拷貝一個ostream。如果我們希望bind一個函數而不希望拷貝參數,就需要用標准庫的ref函數。

for_each(words.begin(), words.end(), bind(printf, ref(os), _1, ' '));

函數ref返回一個對象,包含給定的引用,此對象是可以拷貝的。標准庫中還有cref函數,生成一個保存const引用的類。ref和cref都在頭文件"functional.h"

關於bind1st和bind2nd函數

標准庫中定義了這兩個函數,類似於bind,但是這兩個函數只能分別綁定第一個或第二個參數。由於局限性太強,在C++11中已經被棄用,新的C++應該使用bind。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM