Mẫu hàm hủy
Thuộc phần Lập trình hướng đối tượng trong hành trình C của Coddy. Bài học 13 trên 61.
Mọi đối tượng được tạo bằng malloc cuối cùng đều phải được giải phóng. Cũng như ta viết hàm create_ để xử lý việc cấp phát, ta viết hàm free_ để xử lý việc dọn dẹp. Đây là mẫu hàm hủy.
Điều quan trọng cần hiểu là phải giải phóng theo thứ tự ngược lại với lúc cấp phát. Nếu hàm khởi tạo cấp phát các thành viên bên trong trước rồi mới cấp phát struct, thì hàm hủy phải giải phóng các thành viên của struct trước, sau đó mới giải phóng struct:
typedef struct {
char *name;
int age;
} Person;
void free_person(Person *p) {
if (p == NULL) return; // Kiểm tra an toàn
free(p->name); // Giải phóng thành viên bên trong trước
free(p); // Sau đó giải phóng chính struct
}
Việc kiểm tra NULL ở đầu giúp tránh sự cố nếu ai đó vô tình truyền vào một con trỏ (pointer) không hợp lệ. Sau khi giải phóng chuỗi name bên trong, ta giải phóng chính cấu trúc đó. Nếu giải phóng p trước, ta sẽ mất quyền truy cập vào p->name và gây rò rỉ bộ nhớ.
Cách dùng hàm hủy rất đơn giản:
Person *alice = create_person("Alice", 30);
// ... sử dụng alice ...
free_person(alice); // Giải phóng bộ nhớ sau khi dùng xong
Mẫu này đảm bảo toàn bộ bộ nhớ được giải phóng đúng cách. Nếu không có nó, mọi đối tượng bạn tạo ra sẽ làm rò rỉ bộ nhớ cho đến khi chương trình cạn bộ nhớ.
Thử thách
DễHãy tạo một module Movie minh họa toàn bộ vòng đời của đối tượng: từ tạo đến hủy. Bạn sẽ thực hành viết hàm hủy để giải phóng đúng cách toàn bộ bộ nhớ đã cấp phát, theo đúng thứ tự.
Bạn sẽ tạo ba tệp:
movie.h: Khai báo một cấu trúcMoviegồm hai thành viên:char *title(một chuỗi được cấp phát động) vàint year. Khai báo cả hàm khởi tạocreate_movie, nhận tiêu đề và năm, lẫn hàm hủyfree_movie, nhận một con trỏ Movie. Dùng include guard với ký hiệuMOVIE_H.movie.c: Triển khai cả hai hàm. Hàm khởi tạo cần cấp phát bộ nhớ cho cấu trúc và chuỗi tiêu đề (đừng quên ký tự kết thúc chuỗi null). Hàm hủy phải giải phóng bộ nhớ theo thứ tự ngược với thứ tự cấp phát: trước tiên là chuỗititlebên trong, sau đó là chính cấu trúc. Để an toàn, hãy kiểm tra NULL ngay đầu hàm hủy.main.c: Tạo một bộ phim, hiển thị thông tin của bộ phim, sau đó giải phóng bộ nhớ đúng cách.
Bạn sẽ nhận hai đầu vào: tiêu đề phim (một chuỗi) và năm phát hành (một số nguyên).
Trong tệp main, dùng create_movie để tạo một bộ phim mới, in thông tin của bộ phim, sau đó gọi free_movie để giải phóng toàn bộ bộ nhớ. Sau khi giải phóng, in một thông báo xác nhận.
In đầu ra theo định dạng sau:
Movie: {title} ({year})
Memory freedVí dụ, với đầu vào Inception và 2010, đầu ra sẽ là:
Movie: Inception (2010)
Memory freedHãy nhớ: bí quyết để viết hàm hủy đúng cách là giải phóng theo thứ tự ngược lại. Thành phần nào được hàm khởi tạo cấp phát trước tiên thì được giải phóng sau cùng, còn thành phần nào được cấp phát sau cùng thì được giải phóng trước tiên.
Tự làm thử
#include <stdio.h>
#include <stdlib.h>
#include "movie.h"
int main() {
char title[100];
int year;
// Đọc đầu vào
scanf("%[^\n]", title);
scanf("%d", &year);
// TODO: Tạo một bộ phim bằng create_movie
// TODO: In ra thông tin bộ phim theo định dạng:
// Movie: {title} ({year})
// TODO: Giải phóng bộ nhớ của bộ phim bằng free_movie
// TODO: In ra "Memory freed"
return 0;
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Kiến thức cơ bản về lập trình mô-đun
Tệp tiêu đềInclude guardTệp mã nguồnHàm staticÔn tập: Máy tính mô-đun4Tính đóng gói
Khái niệm con trỏ mờĐịnh nghĩa struct mờHàm truy xuất và hàm gánKiểm tra tính hợp lệ trong hàm gánÔn tập: Hộp bí mật2Đối tượng và phương thức
Struct dưới dạng đối tượngCon trỏ 'Self'Tính đúng đắn của constCon trỏ và giá trịPhương thức hỗ trợÔn tập: trình quản lý Point5Dự án: Tài khoản ngân hàng đơn giản
Thiết lập dự ánTriển khai tài khoản3Vòng đời đối tượng
Mẫu hàm khởi tạoMẫu hàm hủyKhởi tạo trên ngăn xếpSao chép sâuÔn tập: lớp bao bọc chuỗi6Kế thừa bằng cách kết hợp
Nhúng structQuy tắc thành viên đầu tiênTruy cập thành viên lớp chaUpcastingÔn tập: hệ phân cấp hình dạngTự luyện tập: Trình biên dịch C online