??? 對于lambda庫的介紹,大家還是去看boost文檔。我對lambda的原理也是一知半解,有興趣的可以去學習一些函數式編程語言的相關理論。
lambda的使用方式確實顛覆了傳統的過程式語言的一些方面。
???
在C++中,可以這樣理解:lambda的功能就是把一段代碼當作參數,傳給一個函數。在被調用函數中,會用這段參數代碼作一個處理。而且這段參數代碼并
不是只能寫一些靜態的過程,它可以有參數。在C++中,這段參數代碼實際上是一個functor.
我們看一個最簡單的例子:
vector<int> v(10)
for_each(v.begin(), v.end(), cout << _1 << '\n');
這個cout << _1 << '\n',就是一個lambda函數。
lambda并不是只能處理這樣簡單的例子,還可以有分支、循環等控制語句。正好工作中用到,順便貼出來。
例子說明:這是一個收集windows信息的代碼的一部分,下面這段代碼是收集磁盤類型和磁盤空間的。
using namespace boost::lambda;
//下面三行,是因為windows API是__stdcall修飾的,因此,用function來包裝一下。
boost::function<UINT (LPCTSTR)> drtype = ::GetDriveType;
boost::function<BOOL (LPCTSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD)>
drfree = ::GetDiskFreeSpace;
DWORD dwSectorsPerCluster, dwBytesPerSector,
NumberOfFreeClusters, dwTotalNumberOfClusters;
//log 是預定義的,ostream類型
log << "DriveType=";
//dl是盤符列表
for_each(dl.begin(), dl.end(),
( //這個“(“不能少,你就當它是{看待
log << _1 << " " // 這個很簡單
<< bind(drtype, bind(&string::c_str, _1)), //這個,相當于導致drtype(_1.c_str())
//上面的","是被lambda重載的,你當它是“;”
if_ //這個相當于if
(
bind(drfree, bind(&string::c_str, _1)
, &dwSectorsPerCluster, &dwBytesPerSector
, &NumberOfFreeClusters, &dwTotalNumberOfClusters
) > 0 //這個好長,其實很簡單:drfree(1.c_str(), ...) > 0;
)
[ //這個也是重載的,當它是“{“
log << constant(" ") //這個constant是一定要的,這樣這一行才能成為一個lambda表達式
<< var(dwSectorsPerCluster) << constant(" ")
<< var(dwSectorsPerCluster) << constant(" ")
<< var(dwBytesPerSector) << constant(" ")
<< var(NumberOfFreeClusters) << constant(" ")
<< var(dwTotalNumberOfClusters)
],
log << constant(", ")
)
);
log << END_LINE;
??? 在寫比較長的lambda的時候,掌握一個原則,就很簡單了。
????
我把一個lambda表達式叫做一個lambda算子,lambda表達式只能由lambda算子構成。lambda算子之間的運算組合,仍然是
lambda算子。一個普通的C++對象,必須首先轉型成lambda算子才能參與lambda運算。一個復雜的lambda表達式必須注意檢查每一個環
節,確保都是lambda算子(或者可以隱式轉換的)。這樣,結合運算符重載的知識,就不難寫出復雜的lambda表達式了。
ps:在vc7.1中,lambda表達式有錯誤時,編譯出錯信息可是非常壯觀的,不是一般的壯觀哦