Dùng thư viện STL sẽ giúp ích rất nhiều trong việc lập trình trong C++, việc coding sẽ trở nên dễ dàng nếu bạn biết tận dụng các lớp và tính năng mà thư viện STL cung cấp, ở bài này mình sẽ giới thiệu cách sử dụng std::vector thay thế cho việc cấp phát động, trong trường hợp bạn không muốn tạo vùng nhớ trên stack và bạn muốn hủy vùng nhớ sau khi kết thúc hàm hoặc ra ngoài phạm vi của scope giới hạn bằng cặp ngoặc { … }
Cấp phát bộ nhớ theo cách thông thường
Thông thường nếu bạn muốn cấp phát động một vùng nhớ để sử dụng thì bạn sẽ làm như sau:
unsigned char *dataBuffer = new unsigned char[1000];
// Do something here
delete [] dataBuffer;
Việc làm này có một số bất lợi sau:
- Cú pháp khá phức tạp
- Quên delete vùng nhớ đã cấp phát
- Nhầm lẫn giữa delete và delete [] có thể dẫn tới rò rỉ bộ nhớ
- Việc delete hai lần có thể dẫn tới lỗi không lường trước được
- Exception trong quá trình xử lý giữa vùng cấp phát và xóa vùng nhớ sẽ gây rò rỉ vùng nhớ
Một cách làm khác bằng cách sử dụng std::vector
Nhờ việc sắp sếp các phần tử trên bộ nhớ của std::vector là liền kề nhau nên ta có thể dùng nó như một mảng các phần tử
std::vector<unsigned char> dataBuffer(1000);
// Do something
Lợi thế:
- Đơn giản và gọn gàng
- Tự động dọn dẹp vùng nhớ sau khi sử dụng xong
- Exception xãy ra thì vector vẫn được hủy
- Tận dụng được các phương thức mà std::vector cung cấp
- Thư viện giải thuật của STL cung cấp nhiều giải thuật và tính năng cho std::vector như sorting, sum, for_each, …
Truy xuất vùng nhớ của std::vector như thế nào?
-
Truy xuất các phần tử trong dataBuffer: tương tự với mảng, std::vector cung cấp operator[] để truy xuất tới các phần tử VD: dataBuffer[0] = ‘a’;
-
Truyền dataBuffer tới các hàm trong C: giả sử mình có hàm như sau proccess(unsigned char *data); thì để truyền vector dataBuffer vào hàm này mình có thể làm như sau:
process(&dataBuffer[0]);
Hoặc
process(&dataBuffer.front());
Có nhiều phương thức tiện lợi trong std::vector bạn có thể tìm hiểu ở đây: