Khởi tạo trên ngăn xếp
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 14 trên 61.
Không phải đối tượng nào cũng cần được cấp phát trên heap. Khi một struct nhỏ và có vòng đời ngắn, cấp phát nó trên stack sẽ đơn giản và nhanh hơn: không cần malloc, không cần free, không có nguy cơ rò rỉ bộ nhớ.
Thay vì trả về một con trỏ, hàm tạo có thể trả về struct theo giá trị. Toàn bộ struct sẽ được sao chép cho bên gọi:
typedef struct {
int x;
int y;
} Point;
Point create_point(int x, int y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Bên gọi nhận được một bản sao đã được khởi tạo đầy đủ:
Point origin = create_point(0, 0);
Point cursor = create_point(100, 50);
printf("Cursor: (%d, %d)\n", cursor.x, cursor.y);
Không có con trỏ, không cần dọn dẹp. Khi origin và cursor ra khỏi phạm vi, chúng sẽ tự động bị hủy.
Cách này phù hợp nhất với các struct nhỏ không có thành viên được cấp phát động. Với các đối tượng lớn hơn hoặc chứa con trỏ đến bộ nhớ heap, cách dùng mẫu hàm khởi tạo với malloc vẫn là lựa chọn tốt hơn.
Thử thách
DễHãy tạo một module Temperature để tạo các giá trị nhiệt độ trên stack bằng hàm nhà máy. Khác với các hàm khởi tạo dựa trên heap trong những bài học trước, cách này trả về struct theo giá trị: không dùng malloc, không dùng free, chỉ cấp phát đơn giản và hiệu quả trên stack.
Bạn sẽ tạo ba tệp:
temperature.h: Khai báo structTemperaturevới hai thành viên:double celsiusvàchar scale(để lưu 'C' cho độ Celsius). Đồng thời khai báo hai hàm:create_temperature: nhận một giá trị double và trả về structTemperaturetheo giá trị (không phải con trỏ!)temperature_to_fahrenheit: nhận mộtconst Temperature *và trả về nhiệt độ tương đương theo độ Fahrenheit dưới dạng double
TEMPERATURE_H.temperature.c: Triển khai cả hai hàm. Hàm nhà máy của bạn cần tạo một biếnTemperaturecục bộ, khởi tạo các trường của biến (đặtscalethành'C') rồi trả về biến đó. Công thức chuyển đổi là:fahrenheit = celsius * 9.0 / 5.0 + 32.0main.c: Dùng hàm nhà máy để tạo giá trị nhiệt độ và hiển thị cả giá trị Celsius lẫn Fahrenheit.
Bạn sẽ nhận một đầu vào: nhiệt độ theo độ Celsius (dưới dạng double).
Trong tệp chính, dùng create_temperature để tạo struct Temperature với giá trị đã cho. Sau đó in ra giá trị Celsius ban đầu và giá trị tương đương theo độ Fahrenheit.
In đầu ra theo định dạng sau:
Celsius: {celsius}
Fahrenheit: {fahrenheit}Dùng %.2f cho cả hai giá trị để hiển thị hai chữ số thập phân.
Ví dụ, với đầu vào 25.0, đầu ra sẽ là:
Celsius: 25.00
Fahrenheit: 77.00Hãy chú ý cách làm này gọn gàng như thế nào. Bạn nhận được một struct đã khởi tạo đầy đủ mà không cần lo lắng về việc quản lý bộ nhớ. Khi biến Temperature của bạn ra khỏi phạm vi, nó sẽ tự động được dọn dẹp.
Tự làm thử
#include <stdio.h>
#include "temperature.h"
int main() {
double celsius_input;
scanf("%lf", &celsius_input);
// TODO: Dùng create_temperature để tạo một cấu trúc Temperature
// TODO: In giá trị Celsius theo định dạng %.2f
// TODO: Dùng temperature_to_fahrenheit để chuyển đổi và in giá trị Fahrenheit
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