Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024

CodeLearn is an online platform that helps users to learn, practice coding skills and join the online coding contests.

Links

Learning

Training

Fights

Information

About Us

Terms of Use

Help

Help

Discussion

Powered by CodeLearn © 2024. All Rights Reserved. rev 2/5/2024 5:31:56 PM

C++ được biết đến là một ngôn ngữ lập trình đầy mạnh mẽ và độ linh hoạt cao, có khả năng tiếp cận sâu vào ngôn ngữ máy tính. Một trong những nét nổi bật làm nên sự độc đáo của C++ đó là thư viện vector mà nó cung cấp. Vậy vector trong C++ là gì? Hãy cùng tìm hiểu những kiến thức cơ bản nhất về vector C++ trong bài viết dưới đây.

Vector trong C++ là gì?

Vector trong C++ là các mảng động (dynamic array) dùng để lưu trữ dữ liệu. Khác với array – dùng để lưu trữ dữ liệu tuần tự và có bản chất tính, các vector có độ linh hoạt cao hơn nhiều. Vector có thể tự động resize khi có phần tử được chèn hay xoá khỏi array, trong khi đó array thường có kích thước cố định.

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Vector trong C++ là gì?

Các phần tử vector C++ được đặt trong một bộ nhớ liền kề (contiguous storage), cho phép truy cập và duyệt thông qua một trình vòng lặp (iterator).

Vì sao nên sử dụng Vector C++?

Với vector trong C++, các developer không còn phải thực hiện nhiều thao tác thừa thãi, lặp đi lặp lại khi phải làm việc với mảng ở trong C++. Dưới đây là một số ưu điểm của kiểu vector trong C++ so với mảng truyền thống:

  • Không cần phải khai báo kích thước của mảng vì vector có khả năng tự resize.
  • Tự động điều chỉnh kích thước để chèn phần tử nếu vector đã đầy.
  • Cho biết số lượng các phần tử đang được lưu trữ.
  • Cho phép sử dụng chỉ số âm (chẳng hạn như A[-6], A[-5],…).

Cách sử dụng vector trong C++

Để có thể sử dụng được vector trong C++ bạn cần khai báo header vector và thư viện std.

Dưới đây là một số bước để sử dụng vector trong C++:

1. Khai báo thư viện vector


# include<vector>
    using namespace std;

2. Khởi tạo vector

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

3. Thêm phần tử vào cuối vector

vec.push_back(10); // Thêm phần tử 10 vào cuối vector
vec.push_back(20); // Thêm phần tử 20 vào cuối vector

4. Truy cập phần tử của vector

int firstElement = vec[0]; // Truy cập phần tử đầu tiên (index bắt đầu từ 0)
int secondElement = vec.at(1); // Truy cập phần tử thứ hai, sử dụng at() để có kiểm tra chỉ số an toàn

5. Loại bỏ phần tử khỏi vector

vec.pop_back(); // Loại bỏ phần tử cuối cùng của vector

6. Duyệt qua các phần tử của vector

for (int i = 0; i < vec.size(); i++) {
    std::cout << vec[i] << std::endl; // In ra từng phần tử của vector
}
// Hoặc sử dụng iterator
for (auto it = vec.begin(); it != vec.end(); ++it) {
    std::cout << *it << std::endl; // In ra từng phần tử của vector
}
// Hoặc sử dụng range-based for loop (C++11 trở lên)
for (int val : vec) {
    std::cout << val << std::endl; // In ra từng phần tử của vector
}

7. Lấy kích thước của vector

size_t numElements = vec.size(); // Lấy số lượng phần tử hiện tại trong vector

Trên đây là những hàm để sử dụng cho vector trong C++ bạn có thể theo dõi tiếp phần tiếp theo để biết thêm chi tiết.

Standard Template Library là gì?

Standard Template Library (STL) là một tập hợp các lớp mẫu (template class), cung cấp các cấu trúc dữ liệu và hàm phổ biến như list, stack, array,… Đây là một thư viện bao gồm các lớp container, thuật toán và iterator. Vì là một thư viện có tính tổng quát nên mọi phần tử của thư viện đều được tham số hoá. Để làm việc được với STL, các developer cần có kiến thức cơ bản về việc xử lý các template class.

STL bao gồm bốn thành phần cơ bản:

  • Thuật toán.
  • Container.
  • Hàm.
  • Iterator.

Thuật toán

Thuật toán header xác định một tập hợp các hàm được thiết kế đặc biệt để sử dụng trên các phạm vi phần tử. Thành phần này hoạt động trên các container và cung cấp phương thức cho nhiều thao tác của container.

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Thuật toán

Container

Container lưu trữ các đối tương và dữ liệu, với tổng cộng bảy lớp theo tiêu chuẩn “first-class“, ba lớp adaptor và 7 file header cung cấp quyền truy cập vào những container/container adaptor này.

  • Sequence container: Triển khai các cấu trúc dữ liệu có thể được truy cập theo cách tuần tự.
    • vector
    • list
    • deque
    • array
    • forward_list
  • Container adaptor: Cung cấp nhiều giao diện khác cho các container tuần tự.
    • queue
    • priority_queue
    • stack
  • Associative container: Triển khai cấu trúc dữ liệu được sắp xếp, có thể tìm kiếm với độ phức tạp O(logn)
  • Unordered Associative Container: Triển khai cấu trúc dữ liệu không có thứ tự.
    • unordered_set
    • unordered_multiset
    • unordered_map
    • unordered_multimap

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Adaptive container và unordered container

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Sequence container và ordered container

Bạn có thể tìm hiểu thêm cách sắp xếp bằng các thuật toán sắp xếp như QuickSort.

Hàm

STL bao gồm nhiều class có thể overload toán tử gọi hàm. Các instance của những class này được gọi là đối tượng hàm (functor). Các functor cho phép tuỳ chỉnh hoạt động của hàm thông qua các tham số được truyền.

Iterator

Đúng như tên gọi, iterator được sử dụng để làm việc với các chuỗi giá trị. Đây cũng là tính năng chính để đảm bảo tính khái quát hoá của STL.

Các Vector được lưu trữ trong C++ như thế nào?

Trong những phần còn lại của bài viết, ta sẽ tìm hiểu cách sử dụng thư viện vector trong C++. Trước hết, để tạo một vector, ta cần sử dụng cú pháp như dưới đây:

vector <object_type> variable_name;

Ví dụ:


# include <iostream>

# include <vector>

# include <string>
class Car {
public:
    std::string make;
    std::string model;
    int year;
    Car(std::string m, std::string mod, int y) : make(m), model(mod), year(y) {}
    void display() const {
        std::cout << "Brand: " << make << " " << model << ", Year: " << year << std::endl;
    }
};
int main() {
    // Tạo một vector chứa các đối tượng Car.
    std::vector<Car> garage;
    // Thêm các đối tượng Car vào trong vector.
    garage.emplace_back("Vietnix.vn", "VPS,Hosting", 2023);
    garage.emplace_back("Honda", "Accord", 2019);
    garage.emplace_back("Tesla", "Model S", 2021);
    // Hiển thị thông tin của từng chiếc xe trong garage.
    for (const Car& car : garage) {
        car.display();
    }
    return 0;
}

Output:

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Output Vector được lưu trữ trong C++

Ví dụ trên minh họa việc sử dụng vector để lưu trữ các đối tượng trong ngôn ngữ lập trình C++.

Cách Vector ngăn chặn rò rỉ bộ nhớ

Khi một đối tượng Vector vượt ra khỏi ranh giới phạm vi trong code, sẽ tự động thực hiện việc giải phóng các khu vực bộ nhớ dưới quyền kiểm soát của mình. Sự tự quản này không những giảm bớt gánh nặng quản lý bộ nhớ từ phía lập trình viên, mà còn là hệ thống phòng vệ hiệu quả chống lại các lỗi rò rỉ bộ nhớ.


# include <iostream>

# include <vector>
class Widget {
public:
    Widget() { std::cout << "Widget constructed\n"; }
    ~Widget() { std::cout << "Widget destroyed\n"; }
};
int main() {
    {
        std::vector<Widget> widgetList;
        widgetList.push_back(Widget());
        widgetList.push_back(Widget());
        std::cout << "Inside the block\n";
        // Khi ra khỏi block này, widgetList sẽ bị phá hủy
    } // widgetList destructor is called here automatically
    std::cout << "Outside the block\n";
    return 0;
}

Output:

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Kết quả khi chạy hàm ngăn chặn rò rỉ bộ nhớ

Như bạn thấy trong ví dụ, ngay khi block code chứa vector widgetList kết thúc, destructor của std::vector được gọi, tự động giải phóng bộ nhớ và gọi destructor của mỗi đối tượng Widget bên trong. Điều này minh họa rằng không cần thực hiện bất kỳ bước giải phóng bộ nhớ nào một cách thủ công std::vector làm tất cả mọi thứ liên quan đến quản lý bộ nhớ.

Tự động ghi nhớ độ dài của Vector

Khác với mảng động được tích hợp sẵn của C++, vốn không biết được độ dài của mảng, std::vectors tự động theo dõi độ dài của chúng. Để lấy được độ dài của vector, bạn có thể sử dụng hàm size().

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

0

Output:

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Cách tự ghi nhớ kích thước trong vector

Đoạn code trên, bạn sẽ thấy rằng std::vector tự động cập nhật kích thước của mình khi bạn thêm hoặc xóa phần tử. Hàm size() sẽ luôn cung cấp số lượng phần tử hiện tại trong vector.

Nén nhiều giá trị bools trong C++

Trong C++, bạn có thể nén nhiều giá trị boolean sử dụng một số cách khác nhau. Một trong những cách hiệu quả nhất là sử dụng

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

6, đây là một template đặc biệt của

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

7 đã được tối ưu hóa để lưu trữ boolean mà chỉ sử dụng một bit cho mỗi giá trị, thay vì sử dụng ít nhất một byte mà thông thường một biến

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

8 sẽ chiếm dụng.

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

1

Output:

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Ví dụ về cách sử dụng std::vector<bool> để nén các giá trị boolean

Tổng hợp các hàm Vector trong C++ và cách sử dụng

Một vector container trong STL cung cấp nhiều hàm vô cùng hữu ích, trong đó có 3 hàm cơ bản là:

  1. Modifider.
  2. Iterator.
  3. Capacity.
  4. Element access

Modifier

  1. push_back(): Đẩy phần tử vào vị trí cuối của vector. Nếu kiểu đối tượng được truyền dưới dạng tham số trong push_back() không giống với kiểu vector thì sẽ trả về Exception.
  2. assign(): Gán giá trị mới vào các phần tử.
  3. pop_back(): Dùng để pop hoặc xoá phần tử ở cuối vector, đồng thời giảm kích thước của vector đi 1 đơn vị.
  4. insert(): Chèn phần tử mới vào phía trước phần tử trước vị trí trỏ của iterator. Ngoài ra ta cũng có thể thêm đối số

    std::vector<int> vec; // khởi tạo một vector không có phần tử nào

    9 để đếm số lần chèn phần tử.
  5. erase(): Xoá phần tử khỏi container dựa trên vị trí hoặc phạm vi nhất định. Người dùng có thể truyền vị trí của phần tử cần xoá hoặc truyền phạm vi của phần tử.
  6. swap(): Dùng để hoán đổi nội dung của một vetor với vector khác có cùng kiểu (kích thước có thể khác nhau).
  7. clear(): Xoá mọi phần tử của vector container.

Ví dụ:

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

2

Output:

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Ouput của những phương thức trong hàm Modifider

Iterator

  1. begin(): Trả về iterator đang trỏ đến phần tử đầu tiên của vector.
  2. end(): Trả về iterator đang trỏ đến phần tử cuối cùng của vector.

Ví dụ:

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

3

Output:

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Ouput của những phương thức trong hàm Iterator

Trong ví dụ trên, ta đã định nghĩa một vector có tên vec1, sau đó đẩy các giá trị từ 1 đến 10 vào vector bằng một vòng lặp và hàm push_back trong C++. Câu lệnh tiếp theo dùng để in giá trị của vector bằng vòng lặp for, sử dụng begin() và end() để chỉ định điểm đầu và cuối của vòng lặp.

Capacity

  1. size(): Trả về số lượng phần tử có trong vector.
  2. max_size(): Trả về số lượng phần tử lớn nhất vector có thể chứa.
  3. capacity(): Trả về kích thước không gian lưu trữ hiện được cấp cho vector, biểu thị bằng số phần tử dựa trên bộ nhớ được cấp cho vector.
  4. resize(): Đổi kích thước container để chứa được n phần tử. Nếu kích thước hiện tại của vector lớn hơn n thì các phần tử ở sau sẽ bị xoá bị vector. Ngược lại, nếu kích thước hiện tại nhỏ hơn n thì các phần tử sẽ được chèn bổ sung vào cuối vector.
  5. empty(): Trả về True nếu vector đang trống, nếu không thì False.

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

4

Output:

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Ouput của những phương thức trong hàm Capacity

Element access

  1. at(g): Phương thức này cung cấp một tham chiếu đến phần tử nằm tại vị trí ‘g’ của vector, ví dụ sử dụng: ten_vector.at(position).
  2. data(): Phương thức này trả về một con trỏ chỉ đến mảng bộ nhớ mà vector sử dụng để chứa các phần tử của mình, có thể được gọi thông qua: ten_vector.data().
  3. front(): Sử dụng phương thức này để truy xuất phần tử đầu tiên trong vector, có thể gọi bằng: ten_vector.front().
  4. back(): Phương thức này cho phép lấy phần tử cuối cùng trong vector, ví dụ: ten_vector.back().

std::vector<int> vec; // khởi tạo một vector không có phần tử nào

5

Output:

Hướng dẫn dùm hàm nhiều phần tử c++ năm 2024
Ouput của những phương thức trong hàm Element access

Lời kết

Trong bài viết này, ta đã tìm hiểu các kiến thức cơ bản nhất về cách sử dụng vector trong C++ cũng như những hàm phổ biến. Hy vọng qua bài viết này, các bạn đã có thể hình dung ra những cách khác nhau để sử dụng và định nghĩa vector ở trong C++. Nếu còn điều gì thắc mắc, hãy bình luận bên dưới để được hỗ trợ nhé!