作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/
在看《高效編程十八式》中的第一小節的時候介紹了函數對象方法和Lambda運算式,以便完成“如果需要對函數指標進行更加靈活的定製”。
假設任務判斷奇偶數,為了達到資料封裝,我們使用函數對象的方法:
#include
#include
#include
using namespace std;
class Functor
{
public:
// The constructor.
explicit Functor(int& evenCount)
: _evenCount(evenCount)
{
}
void operator()(int n)
{
cout << n;
if (n % 2 == 0)
{
cout << " is even " << endl;
// Increment the counter.
_evenCount++;
}
else
{
cout << " is odd " << endl;
}
}
private:
int& _evenCount; // the number of even variables in the vector
};
int main()
{
vector<int> v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}
int evenCount = 0;
for_each(v.begin(), v.end(), Functor(evenCount));
cout << "There are " << evenCount
<< " even numbers in the vector." << endl;
}
我們使用了一個類,這個類的作用就是判斷奇偶並且進行計數,在for_each迴圈中,我們將這個Functor作為一個函數對象傳入,此時調用Functor的建構函式,建立一個臨時對象,當作用於vector每一個成員時,重載的()運算子發揮作用,表現的像個函數指標。顯然這種方法在增加靈活性的同時卻十分費力的寫了一個如此長的類。
同樣的任務我們使用Lambda運算式再寫一遍:
#include
#include
#include
using namespace std;
int main()
{
vector<int> v;
for (int i = 0; i < 10; ++i)
{
v.push_back(i);
}
int evenCount = 0;
for_each(v.begin(), v.end(), [&evenCount] (int n) {
cout << n;
if (n % 2 == 0)
{
cout << " is even " << endl;
// Increment the counter.
evenCount++;
}
else
{
cout << " is odd " << endl;
}
});
cout << "There are " << evenCount
<< " even numbers in the vector." << endl;
}
在這裡我們在for_each的傳入函數部分使用lambda運算式寫了一個類似於Java中的匿名函數的東西。整個程式顯得自然順暢。[]欄位是lambda運算式的外部變數捕獲規則欄位,=表示按值訪問,&表示按引用訪問(這兩個是定義預設捕獲規則時使用,若指定單個變數的規則,則使用&在變數名前邊表示引用,而按值則直接寫變數名即可),若沒有則不能訪問任何外部變數。而()表示函數體的變數列表,這個與一般的函數沒有什麼區別。
1. Lambda運算式的文法:
以下邊的這個例子來說明文法:
#include
#include
#include
using namespace std;
// The number of elements in the vector.
const int elementCount = 9;
int main()
{
vector<int> v(elementCount, 1);
int x = 1;
int y = 1;
generate_n(v.begin() + 2, elementCount - 2, [&, y]() mutable throw() -> int {
// Generate current value.
int n = x + y;
// Update previous two values.
x = y;
y = n;
return n;
});
// Print the contents of the vector.
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
cout << endl;
cout << x << " " << y << endl;
}
我們看到generate_n這個STL方法,在第三個參數位置上使用了Lambda運算式:
[&, y]() mutable throw() –> int{}
首先,如前所述,[ ]表示外部變數捕獲規則欄位,若是不帶有變數名稱的則定義的是整個運算式的預設的捕獲規則,在這裡是引用;若指明了某一個變數則表示這個變數是單獨定義捕獲規則的,這裡的y就是單獨定義為按值捕獲。
第二個欄位是( ),這是傳入參數欄位,類似於函數,只是它不能有預設參數、不能有變長參數列表,必須有變數名。這個欄位是可選欄位。
第三個欄位是mutable欄位,若設定為mutable則按值捕獲的外部變數的副本在運算式內可以被修改,否則會出現read only的錯誤。這個欄位可選。
第四個欄位是throw欄位,限定能夠拋出哪些異常。這個欄位可選。
第五個欄位是->欄位,表示的返回參數類型。若只有一個返回語句的話,也可以省略這個欄位,由編譯器自行判斷,雖然並不建議這麼做。當然,若沒有傳回值就直接省略這個欄位。
註:g++的編譯方式為g++-4.5 以上,加上--std=c++0x標識
最後我們再寫一個例子:
#include
#include
#include
int main()
{
using namespace std;
// Create a list of integers with a few initial elements.
list<int> numbers;
numbers.push_back(13);
numbers.push_back(17);
numbers.push_back(42);
numbers.push_back(46);
numbers.push_back(99);
// Use the find_if function and a lambda expression to find the
// first even number in the list.
const list<int>::const_iterator result =
find_if(numbers.begin(), numbers.end(),
[](int n) { return (n % 2) == 0; });
// Print the result.
if (result != numbers.end())
{
cout << "The first even number in the list is "
<< (*result)
<< "."
<< endl;
}
else
{
cout << "The list contains no even numbers."
<< endl;
}
}
參考文獻:
- http://msdn.microsoft.com/en-us/library/dd293603.aspx
- http://msdn.microsoft.com/en-us/library/dd293599.aspx
作者:gnuhpc
出處:http://www.cnblogs.com/gnuhpc/