Bỏ qua để đến nội dung

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.

#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>

#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;
}
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.

std::vector<int> numbers = {1, 2, 3};
std::cout << numbers.size() << std::endl; // 3
std::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)
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 << " ";
}
#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”.

#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/delete thủ 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
  • 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::vector thay vì mảng C-style trong hầu hết các trường hợp