Lambda expression trong C++

Lambda expression là một cách đơn giản và nhanh chóng để tạo một Functor. lambda expression là một prvalue mà kết quả của nó là một đối tượng gọi là closure object (closure object là object của class vô danh, duy nhất – closure type class), nó hoạt động như 1 function object. C++ bắt đầu hỗ trợ lambda expression từ C++11.

C++ lambda expression có thể truy cập đến các biến ở ngữ cảnh xung quanh (capture variables from the surrounding context) và thường được dùng như 1 tham số truyền vào cho 1 function khác. Với những hàm chỉ dùng ở một chỗ duy nhất thì thay vì phải tạo function hoặc functor với tên tuổi đàng hoàng thì chúng ta có thể đơn giản là dùng lambda để định nghĩa nó inline , nhanh chóng, thuận tiện.

Một lambda thông thường sẽ gồm 3 thành phần:
  • Capture list: []
  • Parameter list (optional – có thể có hoặc không): ()
  • Function body: {}
cả 3 thành phần trên đều có thể rỗng. Ví dụ →

Capture list

[] là capture list. Theo mặc định, lambda không thể truy cập các biến trong enclosing scope của nó (enclosing scope của lambda tạm hiểu là scope có chứa khai báo lambda).

Capturing một biến sẽ giúp cho nó có thể được truy cập bên trong lambda (có thể là bản copy – “captured” by value hoặc reference – “captured” by reference). Biến được capture sẽ trở thành 1 phần của lambda và không cần phải truyền vào khi call lambda.

Ví dụ → lambda có thể được call như sau

Parameter list

() là parameter list, nó cũng giống với tham số của hàm bình thường thôi, nếu lambda không có tham số thì có thể dấu (), trừ khi bạn muốn khai báo Mutable Lambda (sẽ nói ở phần sau).

2 cách khai bao lambda bên dưới là như nhau:

Parameter list có thể sử dụng kiểu template (C++11 trở lên) hoặc auto (C++14 trở lên) thay vì kiểu dữ liệu chính xác. Ví dụ dưới đây là 2 lambda dùng để sort một vector cho tất cả các kiểu dữ liệu miễn là kiểu dữ liệu đó có toán tử so sánh <.


Function body

{} là thân hàm, cũng giống như thân hàm bình thường nó sẽ chứa các xử lý logic của hàm. Không có gì đặc biệt.


Calling a lambda

Lambda có thể được call sử dụng operator () giống như các functor bình thường →


Return Type (Kiểu trả về) của lambda

Theo mặc định thì kiểu trả vể của lambda được nội suy từ thân hàm. Ví dụ lambda sau có return type là bool Ngoài ra bạn cũng có thể chỉ định kiểu trả về của lambda một cách tường minh như sau →

Mutable Lambda

Theo mặc định, trong lambda không được phép thay đổi giá trị của những biến được “captured by value”, những biến đó là immutable (không thể thay đổi).

Tuy nhiên chúng ta có thể bypass bằng cách sử dụng keyword mutable Nếu lambda sử dụng cả mutable và khai báo cả return type thì cú pháp như sau →

Ví dụ về sự thuận tiện của lambda

Giả sử ta cần sắp xếp 1 dãy số nguyên
  • Trước C++11: sử dụng Functor
  • Từ C++11: có thể sử dụng lambda rất đơn giản và gọn lẹ

— Phạm Minh Tuấn (Shun) —

   

Bài viết liên quan: