9 © 2004, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu 4.2 Mảng và quảnlýbộ nhớ₫ộng Mảng cho phép biểudiễnvàquảnlýdữ liệumộtcách khá hiệuquả: — Đọcvàghidữ liệurất nhanh qua chỉ số hoặcqua ₫ịachỉ —Tiếtkiệmbộ nhớ Các vấn ₫ề củamảng tĩnh: VD: Student student_list[100]; —Số phầntử phảilàhằng số (biếttrước khi biên dịch, ngườisử dụng không thể nhậpsố phầntử, không thể cho số phầntừ là mộtbiến) => kém linh hoạt —Chiếmchỗ cứng trong ngănxếp(₫ốivớibiếncụcbộ) hoặc trong bộ nhớ dữ liệuchương trình (₫ốivớibiếntoàncục) => sử dụng bộ nhớ kém hi ệuquả, kém linh hoạt 10 © 2004, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Mảng ₫ộng Mảng ₫ộng là mộtmảng ₫ượccấpphátbộ nhớ theo yêu cầu, trong khi chương trình chạy #include <stdlib.h> /* C */ int n = 50; float* p1= (float*) malloc(n*sizeof(float)); /* C */ double* p2= new double[n]; // C++ Sử dụng con trỏ₫ểquảnlýmảng ₫ộng: Cách sử dụng không khác so vớimảng tĩnh p1[0] = 1.0f; p2[0] = 2.0; Sau khi sử dụng xong => giải phóng bộ nhớ: free(p1); /* C */ delete [] p2; // C++ 11 © 2004, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Cấpphátvàgiải phóng bộ nhớ₫ộng C: —Hàmmalloc() yêu cầuthamsố là số byte, trả về con trỏ không kiểu(void*) mang ₫ịachỉ vùng nhớ mới ₫ượccấp phát (nằm trong heap), trả về 0 nếu không thành công. —Hàmfree() yêu cầuthamsố là con trỏ không kiểu(void*), giải phóng vùng nhớ có ₫ịachỉ₫ưavào C++: —Toántử new chấpnhậnkiểudữ liệuphầntử kèm theo số lượng phầntử củamảng cầncấpphátbộ nhớ (trong vùng heap), trả về con trỏ có kiểu, trả về 0 nếu không thành công. —Toántử delete[] yêu cầuthamsố là con trỏ có kiểu. —Toántử new và delete còn có thể áp dụng cho cấpphátvà giải phóng bộ nhớ cho mộtbiến ₫ơn, một ₫ốitượng chứ không nhấtthiế tphảimộtmảng. 12 © 2004, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Mộtsố₫iềucầnlưuý Con trỏ có vai trò quảnlýmảng (₫ộng), chứ con trỏ không phải là mảng (₫ộng) Cấpphátbộ nhớ và giải phóng bộ nhớ chứ không phảicấpphát con trỏ và giải phóng con trỏ Chỉ giải phóng bộ nhớ mộtlần int* p; p[0] = 1; // never do it new(p); // access violation! p = new int[100]; // OK p[0] = 1; // OK int* p2=p; // OK delete[] p2; // OK p[0] = 1; // access violation! delete[] p; // very bad! p = new int[50]; // OK, new array 13 © 2004, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Cấpphátbộ nhớ₫ộng cho biến ₫ơn Ý nghĩa: Các ₫ốitượng có thể₫ượctạora₫ộng, trong khi chương trình chạy(bổ sung sinh viên vào danh sách, vẽ thêm mộthìnhtrongbảnvẽ, bổ sung mộtkhâutronghệ thống, ) Cú pháp int* p = new int; *p = 1; p[0]= 2; // the same as above p[1]= 1; // access violation! int* p2 = new int(1); // with initialization delete p; delete p2; Student* ps = new Student; ps->code = 1000; delete ps; Mộtbiến ₫ơn khác vớimảng mộtphầntử! 14 © 2004, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Ý nghĩacủasử dụng bộ nhớ₫ộng Hiệusuất: —Bộ nhớ₫ượccấpphát₫ủ dung lượng theo yêu cầuvàkhi ₫ượcyêucầutrongkhichương trình ₫ãchạy —Bộ nhớ₫ượccấpphátnằm trong vùng nhớ tự do còn lạicủa máy tính (heap), chỉ phụ thuộc vào dung lượng bộ nhớ của máy tính —Bộ nhớ có thể₫ượcgiải phóng khi không sử dụng tiếp. Linh hoạt: —Thờigian"sống" củabộ nhớ₫ượccấpphát₫ộng có thể kéo dài hơnthời gian "sống" củathựcthể cấpphátnó. —Cóthể mộthàmgọilệnh cấpphátbộ nhớ, nhưng mộthàm khác giải phóng bộ nhớ. —Sự linh hoạtcũng dễ dẫn ₫ếnnhững lỗi"ròrỉ bộ nhớ". 15 © 2004, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Ví dụ sử dụng bộ nhớ₫ộng trong hàm Date* createDateList(int n) { Date* p = new Date[n]; return p; } void main() { int n; cout << "Enter the number of your national holidays:"; cin >> n; Date* date_list = createDateList(n); for (int i=0; i < n; ++i) { } for ( ) { cout << } delete [] date_list; } 16 © 2004, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Tham số₫ầuralàcon trỏ? void createDateList(int n, Date* p) { p = new Date[n]; } void main() { int n; cout << "Enter the number of your national holidays:"; cin >> n; Date* date_list; createDateList(n, date_list); for (int i=0; i < n; ++i) { } for ( ) { cout << } delete [] date_list; } . 9 © 20 04, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu 4 .2 Mảng và quảnlýbộ nhớ₫ộng Mảng cho phép biểudiễnvàquảnl dữ liệumộtcách khá hiệuquả: — Đọcvàghidữ liệurất nhanh qua. ngănxếp(₫ốivớibiếncụcbộ) hoặc trong bộ nhớ dữ liệuchương trình (₫ốivớibiếntoàncục) => sử dụng bộ nhớ kém hi ệuquả, kém linh hoạt 10 © 20 04, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Mảng ₫ộng Mảng. /* C */ delete [] p2; // C++ 11 © 20 04, HOÀNG MINH SƠN Chương 4: Khái quát về cấutrúcdữ liệu Cấpphátvàgiải phóng bộ nhớ₫ộng C: —Hàmmalloc() yêu cầuthamsố là số byte, trả về con trỏ không kiểu(void*)