C++(std::vector)

做梦当财神發表於2024-09-07

目錄
  • 1. 特性
  • 2. 常用成員函式
    • 2.1 建構函式
    • 2.2 元素訪問
    • 2.3 修改容器
    • 2.4 容量相關
    • 2.5 迭代器
  • 3. 記憶體管理與效率
  • 4. 示例:
  • 5. 效能分析:



std::vector 是 C++ 標準庫中的一個動態陣列容器,位於 #include <vector> 標頭檔案中。它是一個模板類,可以儲存任何型別的物件,並根據需要動態調整其大小。std::vector 提供了高效的隨機訪問、尾部插入/刪除操作(O(1)),但在中間插入或刪除元素的效能較差(O(n))。



1. 特性

  1. 動態大小std::vector 能自動調整大小,隨著元素的增加,容量會自動擴充套件。
  2. 連續記憶體儲存:由於 std::vector 的儲存空間是連續的,它支援像陣列一樣的隨機訪問,時間複雜度為 O(1)。
  3. 自動管理記憶體std::vector 自動管理記憶體的分配和釋放,不需要手動呼叫 newdelete
  4. 模板類:可以儲存任意型別的物件,必須在建立 std::vector 時指定儲存的物件型別,例如 std::vector<int> 儲存整數,std::vector<std::string> 儲存字串。
  5. 支援範圍檢查:透過 at() 方法訪問元素時會進行範圍檢查,如果索引越界會丟擲 std::out_of_range 異常,而使用 operator[] 則不會進行檢查。


2. 常用成員函式

2.1 建構函式

  • std::vector<T> v;:建立一個空的向量。
  • std::vector<T> v(n);:建立一個包含 n 個預設值為 T() 的元素的向量。
  • std::vector<T> v(n, value);:建立一個包含 n 個值為 value 的元素的向量。
  • std::vector<T> v{elements...};:透過初始化列表來初始化 std::vector

2.2 元素訪問

  • v[i]:返回向量中第 i 個元素(不進行邊界檢查)。
  • v.at(i):返回向量中第 i 個元素(進行邊界檢查)。
  • v.front():返回第一個元素。
  • v.back():返回最後一個元素。
  • v.data():返回指向儲存陣列的指標。

2.3 修改容器

  • v.push_back(value):在向量的末尾新增元素 value
  • v.pop_back():刪除向量中的最後一個元素。
  • v.insert(iterator, value):在指定位置插入元素。
  • v.erase(iterator):刪除指定位置的元素。
  • v.clear():刪除所有元素,使向量為空。
  • v.resize(n):調整向量大小為 n,若 n 大於當前大小,增加的元素將初始化為預設值。
  • v.reserve(n):預留空間至少能容納 n 個元素,避免多次分配記憶體。

2.4 容量相關

  • v.size():返回向量中當前元素的數量。
  • v.capacity():返回向量當前容量,即不重新分配記憶體的情況下,最多能容納多少元素。
  • v.empty():判斷向量是否為空。

2.5 迭代器

  • v.begin():返回指向第一個元素的迭代器。
  • v.end():返回指向最後一個元素之後的迭代器。
  • v.rbegin():返回指向最後一個元素的反向迭代器。
  • v.rend():返回指向第一個元素之前的反向迭代器。


3. 記憶體管理與效率

  • std::vector 的記憶體分配具有一定的增長策略,當容量不足時,會重新分配一個更大的記憶體塊(通常是當前容量的 1.5 倍或 2 倍),並將現有元素複製到新的記憶體塊中。這種策略可以減少多次分配和複製的開銷,但也可能導致暫時的記憶體浪費。

  • 使用 reserve() 可以預先分配足夠的空間,從而避免多次擴容帶來的開銷,特別是在可以預測元素數量時。

  • shrink_to_fit():這個方法請求減少容量以匹配大小,不過實現可以選擇忽略此請求。它可能會將未使用的空間釋放給作業系統。



4. 示例:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 新增元素
    v.push_back(6);

    // 訪問元素
    std::cout << "Element at index 2: " << v[2] << std::endl;
    std::cout << "First element: " << v.front() << std::endl;
    std::cout << "Last element: " << v.back() << std::endl;

    // 修改元素
    v[1] = 10;

    // 輸出向量的所有元素
    for (int x : v) {
        std::cout << x << " ";
    }
    std::cout << std::endl;

    // 刪除最後一個元素
    v.pop_back();

    // 輸出當前大小和容量
    std::cout << "Size: " << v.size() << std::endl;
    std::cout << "Capacity: " << v.capacity() << std::endl;

    return 0;
}


5. 效能分析:

  • 時間複雜度:
    • 訪問元素的時間複雜度為 O(1)。
    • 在尾部插入或刪除元素的時間複雜度為攤銷 O(1),因為擴充套件操作在多次插入後才會觸發。
    • 插入或刪除元素(非尾部)的時間複雜度為 O(n),因為插入或刪除操作需要移動後續元素。
  • 記憶體重分配開銷:擴充套件向量容量時會進行記憶體重分配,這時所有的元素會被複制到新的記憶體地址,因此在頻繁插入大量元素時,提前使用 reserve() 可以提高效率。

std::vector 是 C++ 中最常用的容器之一,因其靈活的動態陣列功能、優秀的效能和易用性而廣受歡迎。儘管它的動態擴充套件會有一定的開銷,但透過適當的預分配(使用 reserve())和合理的使用方式,std::vector 可以滿足大多數應用場景中的效能需求。



相關文章