C++ 11 đã giới thiệu biểu thức lambda để cho phép chúng ta viết một hàm nội tuyến có thể được sử dụng cho các đoạn mã ngắn mà không có sử dụng lại và không cần phải đặt tên. Ở dạng đơn giản nhất, biểu thức lambda có thể được định nghĩa như sau:
[ capture clause ] (parameters) -> return-type
{
definition of method
}
Nói chung kiểu trả về trong biểu thức lambda được đánh giá bởi chính trình biên dịch và chúng ta không cần chỉ định rõ ràng và phần kiểu trả về có thể bị bỏ qua nhưng trong một số trường hợp phức tạp như trong câu lệnh điều kiện, trình biên dịch không thể thực hiện đúng kiểu trả về mà chúng ta cần xác định giúp nó.
Dưới đây là đoạn mã minh hoạ các cách sử dụng khác nhau của biểu thức lambda:
#include <bits/stdc++.h>
using namespace std;
// Hàm để in vector
void printVector(vector<int> v)
{
// biểu thức lambda để in vector
for_each(v.begin(), v.end(), [](int i)
{
std::cout << i << " ";
});
cout << endl;
}
int main()
{
vector<int> v {4, 1, 3, 5, 2, 3, 1, 7};
printVector(v);
// đoạn mã bên dưới tìm phần tử đầu tiên lớn hơn 4
// find_if tìm một phần tử sao cho hàm (đối số thứ
// ba) trả về true
vector<int>:: iterator p = find_if(v.begin(), v.end(), [](int i)
{
return i > 4;
});
cout << "First number greater than 4 is : " << *p << endl;
// săp xếp vector thứ tự giảm dần được tính bởi biểu thức lambda
// Trình biên dịch có thể tự xác định được kiểu trả về là bool,
// nên có thể bỏ đi trong trường hợp này.
sort(v.begin(), v.end(), [](const int& a, const int& b) -> bool
{
return a > b;
});
printVector(v);
// đếm các số lớn hơn hoặc bằng 5
int count_5 = count_if(v.begin(), v.end(), [](int a)
{
return (a >= 5);
});
cout << "The number of elements greater than or equal to 5 is : "
<< count_5 << endl;
// loại bỏ các phần tử trùng lặp sau khi sắp xếp
p = unique(v.begin(), v.end(), [](int a, int b)
{
return a == b;
});
// sửa kích thước vector cho bằng với tổng số khác nhau.
v.resize(distance(v.begin(), p));
printVector(v);
// tính tổng tích luỹ của các kết quả được trả về
// bởi hàm cung cấp ở đối số thứ ba
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int f = accumulate(arr, arr + 10, 1, [](int i, int j)
{
return i * j;
});
cout << "Factorial of 10 is : " << f << endl;
//Ta cũng có thể truy cập biểu thức bằng cách lưu nó vào một biến
auto square = [](int i)
{
return i * i;
};
cout << "Square of 5 is : " << square(5) << endl;
}
Kết quả:
4 1 3 5 2 3 1 7
First number greater than 4 is : 5
7 5 4 3 3 2 1 1
The number of elements greater than or equal to 5 is : 2
7 5 4 3 2 1
Factorial of 10 is : 3628800
Square of 5 is : 25
Một biểu thức lambda có thể có nhiều sức mạnh hơn một hàm thông thường bằng cách có quyền truy cập vào các biến từ phạm vi xung quanh. Chúng ta có thể nắm chụp các biến bên ngoài từ phạm vi xung quanh bằng ba cách:
- Tham chiếu [&]
- Tham trị [=]
- Kết hợp cả hai [a, &b]
Một lambda với mệnh đề chụp rỗng [] chỉ có thể truy cập những biến cục bộ của nó. Các cách chụp được trình bày dưới đây:
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<int> v1 = {3, 1, 7, 9};
vector<int> v2 = {10, 2, 7, 16, 9};
// truy cập v1 và v2 tham chiếu
auto pushinto = [&] (int m)
{
v1.push_back(m);
v2.push_back(m);
};
// nó đẩy 20 vào cả hai v1 và v2.
pushinto(20);
// truy cập v1 bằng sao chép
[v1]()
{
for (auto p = v1.begin(); p != v1.end(); p++)
{
cout << *p << " ";
}
};
int N = 5;
// đoạn mã bên dưới tìm phần tử đầu tiên lớn hơn N
// [N] chỉ có thể truy cập qua tham trị.
vector<int>:: iterator p = find_if(v1.begin(), v1.end(), [N](int i)
{
return i > N;
});
cout << "First number greater than 5 is : " << *p << endl;
// đếm số phần tử lớn hơn hoặc bằng N
// [=] acó thể truy cập tất cả các biến xung quanh.
int count_N = count_if(v1.begin(), v1.end(), [=](int a)
{
return (a >= N);
});
cout << "The number of elements greater than or equal to 5 is : "
<< count_N << endl;
}
Kết quả:
First number greater than 5 is : 7
The number of elements greater than or equal to 5 is : 3
Để lại một bình luận