std::array
#include <array>
template <class T, size_t N> class array;
std::array trong C++ (được giới thiệu từ C++11) là một container tuần tự (sequence container) cung cấp mảng có kích thước cố định với các tính năng của thư viện chuẩn (STL). Nó tương tự như mảng C-style nhưng an toàn hơn và dễ sử dụng hơn.
Tham số
T
- Kiểu dữ liệu của các phần tử trong array.
N
- Kích thước của array (số lượng phần tử), phải là một hằng số nguyên xác định tại thời điểm biên dịch.
array
- Tên của array bạn muốn tạo.
Đặc điểm
- Kích thước cố định: Kích thước của std::array được xác định tại thời điểm biên dịch và không thể thay đổi trong quá trình chạy.
- Truy cập ngẫu nhiên: Giống như mảng C-style, std::array cho phép truy cập ngẫu nhiên các phần tử thông qua toán tử
[]
hoặc hàmat()
với độ phức tạpO(1)
. - Lưu trữ liên tục: Các phần tử trong std::array được lưu trữ liên tục trong bộ nhớ, giống như mảng C-style.
- An toàn và hiệu quả hơn mảng tĩnh:
- Cung cấp các hàm thành viên kiểm tra chỉ số như
at()
(ném ngoại lệ khi truy cập ngoài phạm vi). - Hỗ trợ các thao tác của container STL như
begin()
,end()
,sort()
,find()
,copy()
,...
- Cung cấp các hàm thành viên kiểm tra chỉ số như
- Tuân theo giao diện của STL container: Tích hợp tốt với các thuật toán trong STL (Standard Template Library).
- Hiệu năng tốt: Do lưu trữ các phần tử liên tiếp trong bộ nhớ, giống như mảng C thuần, std::array không có chi phí quản lý động như std::vector và có kích thước cố định giúp nó phù hợp với các ứng dụng yêu cầu hiệu năng cao.
- Không tự động quản lý bộ nhớ: std::array không tự động cấp phát lại bộ nhớ như std::vector. Kích thước của nó là cố định.
- Copy/Move: std::array hỗ trợ copy constructor và move constructor (C++11).
- Biết kích thước tại thời điểm biên dịch: Kích thước của std::array là một phần của kiểu dữ liệu, do đó nó được biết tại thời điểm biên dịch.
- Khi nào nên sử dụng std::array:
- Khi bạn cần một mảng có kích thước cố định.
- Khi bạn muốn tránh chi phí quản lý bộ nhớ động của std::vector.
- Khi bạn cần sự an toàn và tiện lợi hơn so với mảng C-style.
- Khi bạn muốn sử dụng các tính năng của thư viện chuẩn STL cho mảng.
Ví dụ:
#include <iostream>
#include <array>
int main() {
// Khai báo mảng
std::array<int, 5> arr = {1, 2, 3, 4, 5};
// Truy cập phần tử
std::cout << "Element at index 2: " << arr.at(2) << "\n";
// Duyệt qua mảng
std::cout << "Array elements: ";
for (int x : arr) {
std::cout << x << " ";
}
std::cout << "\n";
// Hoán đổi và gán giá trị
std::array<int, 5> arr2;
arr2.fill(10);
arr.swap(arr2);
// In sau khi hoán đổi
std::cout << "Array after swap: ";
for (int x : arr) {
std::cout << x << " ";
}
return 0;
}
Các cách phổ biến khai báo và khởi tạo một std::array
-
Khai báo mảng không khởi tạo giá trị:
Khi không cung cấp giá trị khởi tạo, các phần tử trong std::array sẽ được khởi tạo mặc định (với kiểu dữ liệu nguyên thủy thì thường là 0, còn với kiểu không nguyên thủy thì constructor mặc định sẽ được gọi).
// Mảng có kích thước 5, các phần tử được khởi tạo mặc định (0).
std::array<int, 5> arr; -
Khởi tạo bằng danh sách khởi tạo (Initializer List):
std::array<int, 5> arr = {1, 2, 3, 4, 5};
Lưu ý- Nếu số phần tử cung cấp ít hơn kích thước
Size
, các phần tử còn lại sẽ được khởi tạo mặc định. - Nếu số phần tử nhiều hơn
Size
, trình biên dịch sẽ báo lỗi.
- Nếu số phần tử cung cấp ít hơn kích thước
-
Khởi tạo tất cả phần tử bằng một giá trị:
Sử dụng phương thức
fill()
để gán tất cả phần tử bằng cùng một giá trị sau khi khai báo.std::array<int, 5> arr;
arr.fill(42); // Gán tất cả các phần tử bằng 42. -
Khởi tạo bằng cách sao chép một std::array khác:
std::array<int, 3> arr1 = {1, 2, 3};
std::array<int, 3> arr2 = arr1; // Sao chép arr1 sang arr2. -
Khởi tạo với kiểu dữ liệu phức tạp:
Bạn có thể sử dụng std::array với bất kỳ kiểu dữ liệu phức tạp nào như
struct
,class
, hoặc con trỏ.struct Point {
int x, y;
};
std::array<Point, 2> points = {{{1, 2}, {3, 4}}}; -
Sử dụng
constexpr
với std::array (C++17 trở lên):std::array có thể được khai báo và khởi tạo trong
constexpr
để sử dụng trong các biểu thức hằng số.constexpr std::array<int, 3> arr = {1, 2, 3};
Các kiểu dữ liệu đặc biệt của std::array
Giống như std::vector, std::array cũng là container tổng quát (generic containers) được thiết kế để lưu trữ bất kỳ kiểu dữ liệu hợp lệ nào trong C++ mà bạn có thể định nghĩa ngoài int
, float
, double
,... như struct
, class
, con trỏ, con trỏ thông minh, container lồng nhau, enum
, tuple
và pair
.
-
Structs (Cấu trúc):
struct Point {
int x, y;
};
std::array<Point, 3> points = {{{1, 2}, {3, 4}, {5, 6}}}; -
Classes (Lớp):
class Rectangle {
public:
int width, height;
Rectangle(int w, int h) : width(w), height(h) {}
int area() const { return width * height; }
};
std::array<Rectangle, 2> rects = {Rectangle(3, 4), Rectangle(5, 6)}; -
Pointers và Smart Pointers:
#include <array>
#include <memory>
#include <iostream>
int main() {
// std::array chứa con trỏ thô
std::array<int*, 3> ptrArray = {new int(10), new int(20), new int(30)};
for (const auto& ptr : ptrArray) {
std::cout << *ptr << " ";
delete ptr; // Giải phóng bộ nhớ
}
std::cout << "\n";
// std::array chứa con trỏ thông minh
std::array<std::shared_ptr<int>, 3> smartPtrArray = {
std::make_shared<int>(40), std::make_shared<int>(50), std::make_shared<int>(60)};
for (const auto& smartPtr : smartPtrArray) {
std::cout << *smartPtr << " ";
}
return 0;
} -
Containers lồng nhau (Nested Containers):
std::array<std::vector<int>, 2> nestedContainers = {{{1, 2, 3}, {4, 5, 6}}};
-
Enums (Kiểu liệt kê):
enum class Color { Red, Green, Blue };
std::array<Color, 3> colors = {Color::Red, Color::Green, Color::Blue}; -
Tuples và Pairs:
#include <array>
#include <tuple>
#include <iostream>
int main() {
std::array<std::pair<int, std::string>, 2> pairArray = {
std::make_pair(1, "One"), std::make_pair(2, "Two")};
for (const auto& pair : pairArray) {
std::cout << pair.first << " - " << pair.second << "\n";
}
std::array<std::tuple<int, double, std::string>, 2> tupleArray = {
std::make_tuple(1, 1.1, "One"), std::make_tuple(2, 2.2, "Two")};
for (const auto& tuple : tupleArray) {
std::cout << std::get<0>(tuple) << ", " << std::get<1>(tuple) << ", "
<< std::get<2>(tuple) << "\n";
}
return 0;
}
Các hàm thành viên
Trình lặp (Iterators)
begin | Trả về một iterator trỏ đến phần tử đầu tiên của std::array |
end | Trả về một iterator trỏ đến vị trí ngay sau phần tử cuối cùng của std::array |
rbegin | Trả về một iterator ngược trỏ đến phần tử cuối cùng của std::array |
rend | Trả về một iterator ngược trỏ tới phần tử trước phần tử đầu tiên của std::array |
cbegin | Trả về một iterator hằng trỏ tới phần tử đầu tiên của std::array |
cend | Trả về một iterator hằng trỏ tới phần tử ngay sau phần tử cuối cùng của std::array |
crbegin | Trả về một iterator ngược hằng (constant reverse iterator) trỏ tới phần tử cuối cùng của std::array |
crend | Trả về một iterator ngược hằng trỏ tới phần tử trước phần tử đầu tiên của std::array |
Dung lượng (Capacity)
size | Trả về số lượng phần tử hiện có trong std::array |
max_size | Trả về số lượng phần tử tối đa mà std::array có thể chứa |
empty | Kiểm tra xem một mảng std::array có rỗng hay không |
Truy cập phần tử
[] | Truy xuất phần tử tại vị trí chỉ định |
at | Truy xuất phần tử tại vị trí chỉ định |
front | Truy xuất phần tử tại vị trí đầu tiên |
back | Truy xuất phần tử tại vị trí cuối cùng |
data | Trả về con trỏ trỏ tới phần tử đầu tiên của vùng lưu trữ bên trong mảng std::array |
Thay đổi nội dung (Modifiers)
fill | Gán một giá trị cụ thể cho tất cả các phần tử trong mảng std::array |
swap | Hoán đổi nội dung của hai mảng std::array |
Toán tử quan hệ | Các toán tử quan hệ trong std::array |