std::vector
std::vector (từ thư viện <vector>) là một mảng động - có thể thay đổi kích thước lúc chạy chương trình, khắc phục hạn chế lớn nhất của mảng C-style. Đây là container được dùng phổ biến nhất trong C++ hiện đại.
Khai báo và khởi tạo
Phần tiêu đề “Khai báo và khởi tạo”#include <vector>#include <iostream>
int main() { std::vector<int> numbers; // Vector rỗng std::vector<int> scores = {90, 85, 70}; // Khởi tạo với giá trị có sẵn std::vector<int> zeros(5, 0); // 5 phần tử, tất cả bằng 0
std::cout << scores[0] << std::endl; // 90
return 0;}<int> trong std::vector<int> chỉ định kiểu dữ liệu của phần tử - vector được xây dựng dựa trên template (đã học ở bài “Hàm inline và hàm template”), nên có thể chứa bất kỳ kiểu dữ liệu nào: std::vector<double>, std::vector<std::string>…
Thêm và xóa phần tử
Phần tiêu đề “Thêm và xóa phần tử”#include <vector>#include <iostream>
int main() { std::vector<int> numbers = {1, 2, 3};
numbers.push_back(4); // Thêm phần tử vào CUỐI numbers.push_back(5); // numbers: {1, 2, 3, 4, 5}
numbers.pop_back(); // Xóa phần tử CUỐI // numbers: {1, 2, 3, 4}
for (int n : numbers) { std::cout << n << " "; }
return 0;}Truy cập phần tử
Phần tiêu đề “Truy cập phần tử”std::vector<int> numbers = {10, 20, 30, 40, 50};
std::cout << numbers[0] << std::endl; // 10 (không kiểm tra phạm vi)std::cout << numbers.at(0) << std::endl; // 10 (CÓ kiểm tra, ném exception nếu sai)std::cout << numbers.front() << std::endl; // 10 (phần tử đầu tiên)std::cout << numbers.back() << std::endl; // 50 (phần tử cuối cùng)Khác với mảng C-style, .at() sẽ ném ra ngoại lệ std::out_of_range nếu chỉ số không hợp lệ, thay vì gây lỗi âm thầm nguy hiểm.
Kích thước và kiểm tra rỗng
Phần tiêu đề “Kích thước và kiểm tra rỗng”std::vector<int> numbers = {1, 2, 3};
std::cout << numbers.size() << std::endl; // 3std::cout << numbers.empty() << std::endl; // 0 (false)
numbers.clear(); // Xóa toàn bộ phần tửstd::cout << numbers.empty() << std::endl; // 1 (true)Duyệt qua vector
Phần tiêu đề “Duyệt qua vector”std::vector<int> numbers = {1, 2, 3, 4, 5};
// Cách 1: dùng chỉ sốfor (size_t i = 0; i < numbers.size(); i++) { std::cout << numbers[i] << " ";}
// Cách 2: range-based for (khuyến nghị - ngắn gọn, an toàn)for (int n : numbers) { std::cout << n << " ";}Chèn và xóa tại vị trí bất kỳ
Phần tiêu đề “Chèn và xóa tại vị trí bất kỳ”#include <vector>#include <iostream>
int main() { std::vector<int> numbers = {1, 2, 4, 5};
numbers.insert(numbers.begin() + 2, 3); // Chèn giá trị 3 vào vị trí chỉ số 2 // numbers: {1, 2, 3, 4, 5}
numbers.erase(numbers.begin() + 1); // Xóa phần tử ở chỉ số 1 // numbers: {1, 3, 4, 5}
for (int n : numbers) { std::cout << n << " "; }
return 0;}begin() trả về một iterator trỏ đến phần tử đầu tiên - khái niệm này sẽ được giải thích chi tiết ở bài “Iterator”.
Vector 2 chiều
Phần tiêu đề “Vector 2 chiều”#include <vector>#include <iostream>
int main() { std::vector<std::vector<int>> matrix = { {1, 2, 3}, {4, 5, 6} };
std::cout << matrix[1][2] << std::endl; // 6
return 0;}Vì sao ưu tiên std::vector hơn mảng C-style?
Phần tiêu đề “Vì sao ưu tiên std::vector hơn mảng C-style?”- Tự động quản lý bộ nhớ - không cần
new/deletethủ công - Có thể thay đổi kích thước linh hoạt (
push_back,pop_back,insert,erase) .at()kiểm tra chỉ số hợp lệ, giúp phát hiện lỗi sớm hơn.size()luôn biết được số lượng phần tử hiện tại - mảng C-style thì không
Tổng kết
Phần tiêu đề “Tổng kết”std::vector<T>là mảng động, tự động thay đổi kích thước, khai báo với#include <vector>push_back()/pop_back()thêm/xóa phần tử ở cuối;insert()/erase()thao tác tại vị trí bất kỳ.size()lấy số lượng phần tử;.at()truy cập an toàn (có kiểm tra phạm vi)- Nên dùng
std::vectorthay vì mảng C-style trong hầu hết các trường hợp