C++ hiện đại và cách làm tương ứng trong C

Lambda trong C++ và cách truyền ngữ cảnh cho callback trong C

Trong bài học này, bạn sẽ dùng lambda của C++ để mang theo dữ liệu cục bộ vào callback, rồi so sánh với cách truyền ngữ cảnh bằng con trỏ void trong C.

Giới thiệu

Lambda tạo ra một hàm không tên ngay tại chỗ và có thể "bắt" (capture) các biến cục bộ xung quanh để dùng bên trong. Trong C, callback không thể tự mang theo dữ liệu, nên dữ liệu ngữ cảnh phải được truyền vào một cách tường minh, thường qua con trỏ void.

Những điểm quan trọng

  • Hiểu cách làm trong C trước khi học các công cụ trừu tượng của C++.
  • Dùng RAII và ngữ nghĩa giá trị (value semantics) để thể hiện quyền sở hữu tài nguyên.
  • Ưu tiên các công cụ an toàn kiểu của C++ thay vì macro và ép kiểu.

Code ví dụ bằng C và C++

C
Chạy code →
main.c
#include <stdio.h>

int above(int value, void *context) {
    return value > *(int *)context;
}

int main(void) {
    int values[] = {2, 7, 4, 9};
    int threshold = 5;
    int count = 0;
    for (int index = 0; index < 4; ++index) {
        count += above(values[index], &threshold);
    }
    printf("%d\n", count);
}
Kết quả khi chạy
2
C++
Chạy code →
main.cpp
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector values{2, 7, 4, 9};
    int threshold = 5;
    auto above = [threshold](int value) {
        return value > threshold;
    };
    std::cout << std::count_if(values.begin(), values.end(), above)
              << '\n';
}
Kết quả khi chạy
2

So sánh C và C++

Hàm above trong C nhận ngưỡng qua tham số void *context và phải ép kiểu về int * trước khi so sánh. Trong C++, lambda bắt biến threshold theo giá trị, nên giữ được thông tin kiểu dữ liệu mà không cần ép kiểu thủ công. Cả hai chương trình đều đếm được 2 giá trị lớn hơn 5.

C

C dùng quy ước đặt tên, callback, macro và struct chứa ngữ cảnh.

C++

C++ có sẵn các công cụ trừu tượng có phạm vi rõ ràng, an toàn kiểu và thường không tốn thêm chi phí khi chạy.

Bài tập mở rộng

Hãy chạy cả hai phiên bản, sau đó thử thay đổi code để quan sát sự khác biệt về mức độ an toàn mà mỗi ngôn ngữ mang lại.

  • Tự viết cơ chế bằng C trước, rồi mới dùng tính năng tương ứng của C++.
  • Thay việc giải phóng tài nguyên thủ công bằng RAII.
  • Kiểm tra xem tính năng có phát sinh cấp phát bộ nhớ hoặc lời gọi hàm ảo hay không.

Luyện tập với thử thách

Áp dụng kiến thức của bài học này để giải một bài toán thực tế. Mỗi thử thách chạy ngay trên trình duyệt, có kiểm thử tức thì và AI nhận xét.

Tất cả thử thách