Sử dụng cơ bản và lưu ý về biểu thức Lambda trong C++

Biểu thức Lambda (hàm ẩn danh) là một tính năng mạnh mẽ trong C++ được giới thiệu từ C++11, thường được sử dụng khi cần tạo các hàm tạm thời như trong std::sort, std::for_each hoặc các callback luồng.

1. Cú pháp cơ bản của Lambda

[capture](parameters) -> return_type {
    // thân hàm
};
  • capture: Dùng để bắt giữ các biến từ phạm vi hiện tại.
  • parameters: Danh sách tham số.
  • return_type: Có thể bỏ qua để compiler suy diễn.
  • body: Nội dung hàm.

2. Ví dụ minh họa

2.1 Lambda đơn giản nhất

auto inChao = []() {
    std::cout << "Chào từ lambda!" << std::endl;
};
inChao();  // Gọi hàm

2.2 Lambda có tham số và giá trị trả về

auto tongHaiSo = [](int a, int b) -> int {
    return a + b;
};
std::cout << tongHaiSo(3, 4); // In ra 7

Kiểu trả về có thể lược bỏ nhờ suy diễn tự động.

2.3 Bắt giữ biến ngoài (giá trị vs tham chiếu)

int a = 10, b = 20;

// Bắt giữ bằng giá trị
auto bangGiaTri = [a, b]() {
    std::cout << "Bắt giữ: " << a + b << std::endl;
};

// Bắt giữ bằng tham chiếu
auto bangThamChieu = [&a, &b]() {
    a += 1; b += 1;
};

bangGiaTri();  // In 30
bangThamChieu(); // Thay đổi a và b

2.4 Bắt giữ tự động: =&

int x = 1, y = 2;

auto lambda1 = [=]() { std::cout << x + y << std::endl; }; // Bắt giữ tất cả bằng giá trị
auto lambda2 = [&]() { x += 10; y += 10; };                // Bắt giữ tất cả bằng tham chiếu

2.5 Sử dụng với std::sort

std::vector<int> v = {4, 2, 5, 1, 3};
std::sort(v.begin(), v.end(), [](int a, int b) {
    return a > b;  // Sắp xếp giảm dần
});

2.6 Lambda có trạng thái với mutable

int dem = 0;
auto lambda = [dem]() mutable {
    dem++;
    std::cout << dem << std::endl;
};
lambda(); lambda(); // In ra 1, 2 - Bản sao được thay đổi nhờ mutable

2.7 Kết hợp với thuật toán chuẩn

std::vector<int> duLieu = {1, 2, 3, 4, 5};
std::for_each(duLieu.begin(), duLieu.end(), [](int giaTri) {
    std::cout << giaTri << " ";
});

2.8 Truyền làm tham số

void thucThiLambda(const std::function<void(int)>& func) {
    func(100);
}

int main() {
    thucThiLambda([](int x) {
        std::cout << "Giá trị: " << x << std::endl;
    });
}

3. Những điểm cần lưu ý

Điểm chú ý Mô tả
Phương thức bắt giữ \[=\] sao chép giá trị, \[&amp;\] bắt giữ tham chiếu
mutable Biến bắt giữ theo giá trị mặc định là hằng, cần thêm mutable để thay đổi
Thời gian sống Dùng tham chiếu biến cục bộ sau khi hàm kết thúc sẽ gây ra truy cập vùng nhớ treo
Suy diễn kiểu Compiler tự động xác định kiểu trả về trừ khi có nhiều nhánh khác nhau
Loại đối tượng Lambda là lớp ẩn danh, dùng auto hoặc std::function để lưu trữ

4. Ứng dụng nâng cao

4.1 Hàm đóng gói có trạng thái

auto demSo = []() {
    int dem = 0;
    return [=]() mutable {
        return ++dem;
    };
}();

std::cout << demSo() << std::endl; // 1
std::cout << demSo() << std::endl; // 2

4.2 Bắt giữ this trong Lambda

class ThietKe {
public:
    void thucHien() {
        int giaTri = 42;
        auto l = [this, giaTri]() {
            std::cout << "giaTri = " << giaTri << ", thanhVien = " << this->thanhVien << std::endl;
        };
        l();
    }
private:
    int thanhVien = 99;
};

Thẻ: C++ Lambda Expressions Anonymous Functions

Đăng vào ngày 2 tháng 7 lúc 06:22