Con trỏ hàm và callback trong C, C++
Trong bài học này, bạn sẽ truyền một hàm vào hàm khác dưới dạng tham số bằng con trỏ hàm trong C và lambda trong C++.
Giới thiệu
Callback là kỹ thuật truyền một hàm vào hàm khác để hàm đó gọi lại khi cần. Nhờ vậy, một thuật toán tổng quát có thể thực hiện hành vi do nơi gọi lựa chọn mà không cần biết chi tiết cài đặt bên trong. Ví dụ, cùng một hàm apply có thể bình phương, nhân đôi hoặc làm bất cứ phép biến đổi nào.
Những điểm quan trọng
- Con trỏ chỉ được trỏ tới đối tượng còn tồn tại, đúng kiểu dữ liệu, hoặc mang giá trị null.
- Mỗi vùng nhớ được cấp phát chỉ được giải phóng đúng một lần.
- Thể hiện rõ hàm nào sở hữu vùng nhớ (ownership) và dữ liệu nào chỉ được đọc (const).
Code ví dụ bằng C và C++
#include <stdio.h>
int square(int value) { return value * value; }
int apply(int value, int (*operation)(int)) { return operation(value); }
int main(void) {
printf("%d\n", apply(6, square));
return 0;
}
36
#include <functional>
#include <iostream>
int apply(int value, const std::function<int(int)>& operation) {
return operation(value);
}
int main() {
int factor = 6;
std::cout << apply(factor, [](int value) { return value * value; }) << '\n';
}
36
So sánh C và C++
Trong C, tham số int (*operation)(int) là một con trỏ hàm, nhận vào hàm có một tham số int và trả về int, nên apply(6, square) trả về 36. Trong C++, lambda và std::function có thể lưu trữ nhiều loại đối tượng gọi được (callable) phong phú hơn. Với code cần hiệu năng cao, dùng template thường là lựa chọn tốt hơn std::function.
Việc sở hữu và giải phóng vùng nhớ hoàn toàn do lập trình viên tự đảm bảo.
Container và RAII tự động giải phóng tài nguyên khi đối tượng hết thời gian tồn tại.
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.
- Thử với con trỏ null và trường hợp cấp phát bộ nhớ thất bại.
- Chạy chương trình với AddressSanitizer và UndefinedBehaviorSanitizer để phát hiện lỗi bộ nhớ.
- Ghi chú rõ con trỏ nào sở hữu vùng nhớ và con trỏ nào chỉ dùng để đọc.
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