40 C++ STL模板庫9-容器2-vector

C++ STL模板庫9-容器2-vector

文章目錄

  • C++ STL模板庫9-容器2-vector
    • 一、基礎概念
      • 1. 類型成員(Type Members)
      • 2. 模板參數
    • 二、構造函數
      • 1. 語法
      • 2. 示例
    • 三、元素訪問
      • 1. 函數說明
      • 2. 示例代碼
    • 四、容量操作
      • 1. 函數說明
      • 2. 關鍵點說明
      • 3. 關鍵操作解析
      • 4. 操作示例
    • 五、修改
      • 1. 函數說明
      • 2. 關鍵操作解析
      • 3. 操作示例
      • 4. 操作技巧
    • 六、迭代器操作
      • 1. 函數說明
      • 2. 關鍵操作解析
      • 3. 操作示例
      • 4. 注意事項
    • 七、高效操作(C++11+)
      • 1. 函數說明
      • 2. 關鍵操作解析
      • 3. 常見錯誤規避
      • 4. 優先選擇原則
    • 八、非成員函數
      • 1. 函數說明
      • 2. 示例代碼
      • 3. 操作對比總結
    • 九、完整應用示例
      • 1. 類對象的向量
      • 2. 通過數組初始化向量
    • 十、關鍵特性
    • 十一、應用注意事項??
      • 1. 完美轉發陷阱
      • 2. 高性能尾部操作
      • 3. 內存釋放替代方案
      • 4. 函數選擇指南
      • 5. 避免裸指針操作

vector- 動態數組,也叫向量,內存連續,動態管理內存,下標訪問,尾部增刪效率高。是最常用的容器。

一、基礎概念

1. 類型成員(Type Members)

類型說明
value_type元素類型(如 int
allocator_type分配器類型(默認 std::allocator<T>
size_type大小類型(通常 size_t
reference元素引用(value_type&
const_reference常量引用(const value_type&
iterator隨機訪問迭代器
const_iterator常量迭代器

2. 模板參數

  • std::vector<T>(...) v; // T:元素類型, ...:參數

  • 示例:

    #include <vector>vector<int> vn;
    vector<string> vs;// 元素的預分配和初始化
    vector<int> vn (10); // 用0初始化10個元素
    vector<int> vn (10, 5); // 用5初始化10個元素
    

二、構造函數

1. 語法

vector();                        // 默認構造 
vector(size_type count, T value); // 填充構造 
vector(iterator first, iterator last); // 范圍構造 
vector(initializer_list<T> init);      // 初始化列表構造

2. 示例

#include <iostream>
#include <vector>
#include <array>int main() {// ========== 1. 默認構造 ==========std::vector<int> v1;  // 創建空vector std::cout << "v1大小: " << v1.size()  << "\n";  // 輸出 0// ========== 2. 填充構造 ==========std::vector<char> v2(5, 'A');  // 5個'A'std::cout << "v2內容: ";for (char c : v2) std::cout << c;               // 輸出 AAAAA// ========== 3. 范圍構造 ==========std::array<int, 3> arr{10, 20, 30};std::vector<int> v3(arr.begin(),  arr.end());   // 復制數組元素 std::cout << "\nv3內容: ";for (int n : v3) std::cout << n << " ";          // 輸出 10 20 30 // ========== 4. 初始化列表構造 ==========std::vector<std::string> v4 = {"Apple", "Banana", "Cherry"};std::cout << "\nv4內容: ";for (auto& s : v4) std::cout << s << " ";          // 輸出 Apple Banana Cherry// ========== 組合驗證 ==========std::vector<int> v5{ v3.begin(),  // 復用v3的范圍構造 v3.begin()  + 2 };std::cout << "\nv5內容: ";for (int n : v5) std::cout << n << " ";          // 輸出 10 20 return 0;
}
  • 初始化列表的等價操作

    // 以下兩種寫法等價
    std::vector<int> a = {1,2,3};
    std::vector<int> b({1,2,3});  // 顯式構造函數 
    
  • 顯式類型轉換

    // 避免整數類型混淆 
    std::vector<int> v1(5, 2.5);    // 輸出 {2,2,2,2,2}(截斷)
    std::vector<double> v2{5, 2.5}; // 輸出 {5.0, 2.5}(保留精度)
    

三、元素訪問

1. 函數說明

函數說明
at(size_type pos)邊界檢查訪問(越界拋異常)
operator[](size_type pos)無檢查直接訪問
front()首元素引用
back()末元素引用
data()底層數組指針

2. 示例代碼

#include <iostream>
#include <vector>
#include <stdexcept> // 異常處理int main() {std::vector<int> nums{10, 20, 30, 40, 50};// ===== 1. at() std::cout << "at(2): " << nums.at(2) << '\n';     // ? 輸出 30 // ===== 2. operator[] 無檢查訪問 ===== std::cout << "operator[3]: " << nums[3] << '\n';  // ? 輸出 40 // nums[10] = 100; // ? 未定義行為(可能崩潰或數據污染)// ===== 3. front() & back() 端點訪問 =====std::cout << "front(): " << nums.front() << '\n';  // ? 輸出 10(首元素)std::cout << "back(): " << nums.back() << '\n';    // ? 輸出 50(尾元素)// ===== 4. data() 底層指針訪問 =====int* ptr = nums.data();std::cout << "data()[1]: " << ptr[1] << '\n';  // ? 輸出 20 *ptr = 100;  // 修改首元素std::cout << "front()修改后: " << nums.front() << '\n';  // 輸出 100return 0;
}
  • 優先選擇原則:
    • 用戶輸入索引必須用at()安全
    • 內部循環索引訪問用 operator[]高效
    • 和C兼容用data()兼容

四、容量操作

1. 函數說明

函數作用描述時間復雜度內存影響
empty()判斷容器是否為空O(1)
size()獲取當前元素數量O(1)
max_size()系統支持的最大元素數O(1)
capacity()當前預分配內存容量O(1)
reserve(new_cap)預擴容至指定容量O(n)可能重新分配內存
shrink_to_fit()釋放多余內存(非強制)O(n)可能縮小容量

2. 關鍵點說明

  • 大小可增可減,引起大小變化的函數包括resize()/push_back()/pop_back()/insert()/erase()
  • 容量只增不減,直接引起容量變化的函數只有reserve()一個。
  • 大小的增加可能導致容量的增加,容量的變化不會引起大小的變化。
  • 通過resize()增加大小,新增部分會被初始化,但是通過reserve()增加容量,新增部分不做初始化。
  • 位于容量范圍內但在大小范圍外的元素,可以通過下標或迭代器訪問,但其值不確定。
  • 無論是大小還是容量,它們的變化永遠發生在向量容器的尾部。

3. 關鍵操作解析

  • 基礎狀態檢測(empty()/size()

    std::vector<int> v;
    std::cout << "初始狀態: " << "empty=" << v.empty()   // 輸出 true << ", size=" << v.size()   // 輸出 0 << "\n";v.push_back(10);
    std::cout << "添加元素后: "<< "empty=" << v.empty()   // 輸出 false << ", size=" << v.size()   // 輸出 1 << "\n";
    
  • 容量動態增長(capacity()/reserve()

    std::vector<std::string> words;
    // 初始容量(實現相關,通常0)
    std::cout << "初始容量: " << words.capacity() << "\n";  // 輸出 0 words.reserve(3);  // 預分配3元素空間 
    std::cout << "reserve(3)后容量: " << words.capacity() << "\n";  // 輸出 3 words = {"A", "B", "C", "D"};  // 可能觸發擴容(容量可能變6)
    std::cout << "超容添加后容量: " << words.capacity() << "\n";  // 輸出 4 
    
  • 極限容量檢測(max_size()

    std::vector<double> data;
    std::cout << "系統支持最大元素數: " << data.max_size() / 1e9 << " 億"  // 示例輸出 2.30584e+09 億<< "\n(實際受限于內存和系統架構)\n";
    
  • 內存回收操作(shrink_to_fit()

    std::vector<char> buffer(1000);
    buffer.erase(buffer.begin()+100, buffer.end());  // 刪除900元素 std::cout << "刪除后: size=" << buffer.size()        // 輸出 100 << ", capacity=" << buffer.capacity()     // 輸出 1000 << "\n";buffer.shrink_to_fit();  // 請求釋放內存 
    std::cout << "shrink后: capacity=" << buffer.capacity()  // 輸出 100(可能)<< "\n(實際效果依賴編譯器實現)\n";
    
  • size() vs capacity() 關系
    在這里插入圖片描述

  • 擴容策略優化(以GCC為例)

    // GCC擴容規則:new_cap = max(2*old_cap, required_size)
    std::vector<int> v;
    v.reserve(1);  // capacity=1 
    v.push_back(1);
    v.push_back(2);  // 觸發擴容 → capacity=2 
    v.push_back(3);  // 再次擴容 → capacity=4 
    
  • shrink_to_fit() 的底層實現

    // 典型實現流程 
    if (size() < capacity()) {vector tmp(*this);        // 拷貝構造新vector(按size分配)swap(tmp);                // 交換數據指針 
    }
    

4. 操作示例

// 向量的大小和容量
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;
void print (vector<int>& vn) {std::cout << "大小:" << vn.size ()     << "   ";std::cout << "容量:" << vn.capacity () << std::endl;for (vector<int>::iterator it = vn.begin ();it != vn.end (); it++)cout << *it << ' ';cout << endl;
}int main (void) {vector<int> v1 (10);print (v1);                 //大小:10   容量:10 //0 0 0 0 0 0 0 0 0 0v1.push_back (23);print (v1);                 //大小:11   容量:20 //0 0 0 0 0 0 0 0 0 0 23v1.resize (5);print (v1);                 //大小:5   容量:20 //0 0 0 0 0v1.resize (30);print (v1);                 //大小:30   容量:30 //0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 for (int i = 0; i < 10; i++)//大小:20   容量:30v1.pop_back ();print (v1);                 //0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0v1.reserve (40);            //大小:20   容量:40print (v1);                 //0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0v1.reserve (10);            //大小:20   容量:40print (v1);                 //0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0v1.insert (v1.begin () + 4, 55);//大小:21   容量:40print (v1);                 //0 0 0 0 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0v1.erase (v1.begin () + 4);//大小:20   容量:40print (v1);                //0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0v1.insert (v1.begin () + 4, 66);//大小:21   容量:40print (v1);                //0 0 0 0 66 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0vector<int>::iterator it =find (v1.begin (), v1.end (), /*66*/88);if (it == v1.end ())cout << "沒找到!" << endl;//沒找到!elsecout << *it << endl;   //66 int arr[] = {12, 56, 77, 45, 98, 100, 2};int *p = find (arr, arr + sizeof (arr) / sizeof (arr[0]), 45);cout << *p << endl;        // 45return 0;
}

五、修改

1. 函數說明

函數說明內存影響
clear()清空所有元素元素銷毀,容量保留
push_back(const T& value)尾部插入元素可能觸發擴容
pop_back()刪除尾部元素尾部元素銷毀(容量不變)
insert(iterator pos, const T& value)指定位置插入插入節點后元素后移
erase(iterator pos)刪除指定元素刪除節點后元素前移
resize(size_type count)調整元素數量增刪默認構造元素
swap(vector& other)交換兩個容器內容僅交換指針
assign()完全替換 vector 內容原元素全銷毀

2. 關鍵操作解析

  • clear() vs resize(0)

    std::vector<int> v{1,2,3};
    v.clear();       // 內存狀態: [  ] 容量=3
    v.resize(0);     // 效果相同(但依賴實現)
    
  • 插入刪除的性能陷阱,頭部插入和尾部插入都會使元素向后移動

    // 連續頭部插入:O(n2) 性能災難!
    for (int i = 0; i < 1000; ++i) v.insert(v.begin(), i);  // 每次插入全體后移 // 優化方案:尾部插入后反轉
    for (int i = 0; i < 1000; ++i) v.push_back(i);
    std::reverse(v.begin(), v.end());
    
  • swap 的原子性優勢

    current_data.swap(new_data); // 原子指針交換
    
  • assign 的隱蔽風險

    std::vector<std::string> names{"Alice", "Bob"};
    std::vector<std::string> temp = names; // 深拷貝備份 names.assign(1000, "Unknown"); // 原元素"Alice","Bob"被銷毀 
    // 若異常拋出:原數據丟失且無恢復!
    

3. 操作示例

#include <iostream>
#include <vector>void print(const std::vector<int>& v, const char* msg) {std::cout << msg << ": [";for (int n : v) std::cout << n << " ";std::cout << "]  容量: " << v.capacity()  << "\n\n";
}int main() {// === 1. 初始狀態 === std::vector<int> nums{10, 20, 30};print(nums, "初始狀態");  // [10 20 30] 容量:3 // === 2. push_back:尾部插入 ===nums.push_back(40); print(nums, "push_back(40)");  // [10 20 30 40] 容量:6(觸發擴容)// === 3. pop_back:尾部刪除 === nums.pop_back(); print(nums, "pop_back()");  // [10 20 30] 容量:6 // === 4. insert:指定位置插入 === nums.insert(nums.begin()  + 1, 99);print(nums, "insert(pos1,99)");  // [10 99 20 30] 容量:6// === 5. erase:指定位置刪除 ===nums.erase(nums.begin()  + 2);print(nums, "erase(pos2)");  // [10 99 30] 容量:6// === 6. resize:調整元素數量 === nums.resize(5);  // 新增2個默認0 print(nums, "resize(5)");  // [10 99 30 0 0] 容量:6 nums.resize(2);  // 刪除尾部3個print(nums, "resize(2)");  // [10 99] 容量:6 // === 7. assign:完全替換內容 ===nums.assign({7,  8, 9, 10});print(nums, "assign({7,8,9,10})");  // [7 8 9 10] 容量:6 // === 8. swap:容器交換 === std::vector<int> other{100, 200};nums.swap(other); print(nums, "swap后nums");  // [100 200] 容量:2 print(other, "swap后other"); // [7 8 9 10] 容量:6// === 9. clear:清空元素 === nums.clear(); print(nums, "clear()后");  // [] 容量:2(容量保留!)return 0;
}

4. 操作技巧

  • 容量預分配規則 ,提前把容量分配好,避免在循環里使用push_back()時擴容造成時間開銷

    std::vector<int> data;
    data.reserve(1000);   // 預分配避免多次擴容
    for (int i=0; i<1000; ++i) data.push_back(i); // 無擴容開銷
    
  • 安全刪除模式

    // 刪除特定條件元素(避免迭代器失效)
    auto it = data.begin();
    while (it != data.end()) 
    {if (*it % 2 == 0) it = data.erase(it); // erase返回下一有效迭代器 else ++it;
    }
    
  • 移動語義優化

    // 在 words 尾部插入字符串變量 huge_str 使用移動語義而非拷貝
    std::vector<std::string> words;
    std::string huge_str = get_large_string();
    words.push_back(std::move(huge_str)); // 移動而非拷貝
    

六、迭代器操作

1. 函數說明

begin() / end();       // 正向迭代器
rbegin() / rend();     // 反向迭代器
cbegin() / cend();     // 常量正向迭代器 
crbegin() / crend();   // 常量反向迭代器 

2. 關鍵操作解析

  • 隨機訪問:下標、迭代器

    vn[1] = 40;
    *(vn.begin () + 1) = 40;
    
  • 基礎正向迭代(可讀寫)

    std::vector<int> nums{10, 20, 30};
    // 修改第二個元素 
    auto it = nums.begin() + 1;
    *it = 200;  // ? 允許修改 
    for (auto i = nums.begin(); i != nums.end(); ++i) std::cout << *i << " ";  // 輸出:10 200 30 
    
  • 反向迭代(鏡像操作)

    std::vector<char> letters{'A','B','C'};
    // 逆序輸出并修改首元素 
    auto rit = letters.rbegin();
    *rit = 'Z';  // ? 修改最后一個元素 
    for (auto r = letters.rbegin(); r != letters.rend(); ++r)std::cout << *r << " ";  // 輸出:Z B A 
    
  • 常量反向迭代(安全遍歷)

    const std::string str = "HELLO";
    // 逆序輸出且無法修改 
    for (auto cr = str.crbegin(); cr != str.crend(); ++cr)std::cout << *cr;  // 輸出:OLLEH 
    
  • 迭代器類型轉換關系

    std::vector<int>::iterator          // begin()返回類型 
    std::vector<int>::const_iterator    // cbegin()返回類型 
    std::vector<int>::reverse_iterator  // rbegin()返回類型 
    std::vector<int>::const_reverse_iterator // crbegin()返回類型 
    
  • 與C風格數組的互操作

    int arr[] = {100, 200, 300};
    // 用標準庫函數獲取迭代器 
    auto arr_begin = std::begin(arr);  // ? 等效 &arr[0]
    auto arr_end = std::end(arr);      // ? 等效 &arr[3]
    

3. 操作示例

#include <iostream>
#include <vector>using namespace std;void print (vector<int>& vn) 
{vector<int>::size_type size = vn.size ();cout << "元素個數:" << size << " -> ";for (vector<int>::size_type i = 0; i < size; i++)cout << vn[i] << ' ';cout << endl;
}
void show (vector<int>& vn) 
{for (vector<int>::iterator it = vn.begin (); it != vn.end (); it++)cout << *it << ' ';cout << endl;
}int main (void) 
{vector<int> vn;vn.push_back (10);vn.push_back (20);vn.push_back (30);print (vn);        // 元素個數:3 -> 10 20 30show (vn);        // 10 20 30vn.pop_back ();print (vn);        // 元素個數:2 -> 10 20vn[1] = 40;print (vn);        // 元素個數:2 -> 10 40vector<int>::const_iterator it = vn.begin ();it++;//    (*it)++; // it的目標不可修改,如同常量指針// const xxx *或xxx const *// 而const vector<int>::iterator it 表示迭代器本身不可修改,如同指針常量// xxx * constvector<int> v1 (10);print (v1);        // 元素個數:10 -> 0 0 0 0 0 0 0 0 0 0vector<int> v2 (10, 5);print (v2);        // 元素個數:10 -> 5 5 5 5 5 5 5 5 5 5v1[0] = 100;v1[9] = 200;cout << v1.front () << ' ' << v1.back() << endl;//100 200return 0;
}

4. 注意事項

  • 類型推導陷阱

    auto it1 = nums.begin();   // 推導為iterator(可修改)
    auto it2 = nums.cbegin();  // 推導為const_iterator(安全)
    
  • 范圍循環本質

    for (int n : nums) { /*...*/ } 
    // 等價于:
    for (auto it = nums.begin(); it != nums.end(); ++it)
    
  • 迭代器失效場景

    std::vector<int> data{1,2,3};
    auto it = data.begin();
    data.push_back(4);  // 可能觸發擴容 
    *it = 5;  // ? 迭代器已失效(未定義行為)
    

七、高效操作(C++11+)

1. 函數說明

函數說明
emplace_back(Args&&... args)直接構造尾部元素
emplace(iterator pos, Args&&... args)直接構造指定位置元素

2. 關鍵操作解析

// 直接構造對象(避免拷貝)
struct Point { int x, y; };
std::vector<Point> points;
points.emplace_back(3,  4);  // 直接調用構造函數 
// ? 推薦使用emplace的情況 
v.emplace_back("text",  100);  // 構造參數簡單 
v.emplace(v.begin(),  1, 2, 3); // 插入位置敏感 // ?? 不推薦使用的情況 
v.emplace_back(existing_obj);   // 已有對象直接push_back更清晰 
// 簡單類型(int/double等)
v.push_back(42);           // ? 清晰簡潔 // 多參數構造的復雜類型 
v.emplace_back("ID007",  9.8, Vector3D());  // ? 避免臨時對象 // 在迭代器中間插入 
v.emplace(v.begin()  + 2, config);  // ? 減少元素移動次數 // 對象已存在時 
auto obj = HeavyObject(...);
v.push_back(std::move(obj));   // ? 明確所有權轉移 

3. 常見錯誤規避

錯誤案例后果修正方案
emplace_back({1,2,3})編譯錯誤(初始化列表歧義)emplace_back(std::initializer_list{1,2,3})
emplace(pos, arg) 后使用舊迭代器迭代器失效接收返回的新迭代器 it = emplace(...)
忽略移動語義類型意外拷貝操作對移動類型顯式使用 std::move

4. 優先選擇原則

// 簡單類型(int/double等)
v.push_back(42);          // ? 清晰簡潔 // 多參數構造的復雜類型 
v.emplace_back("ID007", 9.8, Vector3D());  // ? 避免臨時對象 // 在迭代器中間插入 
v.emplace(v.begin() + 2, config);  // ? 減少元素移動次數 // 對象已存在時 
auto obj = HeavyObject(...);
v.push_back(std::move(obj));  // ? 明確所有權轉移 

八、非成員函數

1. 函數說明

函數說明
operator==, !=, <, >容器比較
std::swap(vector<T>& lhs, rhs)特化交換
erase(vector<T>& c, const T& value)刪除匹配值(C++20)
erase_if(vector<T>& c, Predicate pred)條件刪除(C++20)

2. 示例代碼

  • 容器比較運算符

    std::vector a{1,2,3}, b{1,2,3}, c{9};// 等值比較(需元素數量和值相同)
    bool eq = (a == b);  // ? true(深層次比較)// 字典序比較(常用于排序)
    bool lt = (c < a);   // ? true(9<1)
    
  • 特化交換函數

    std::vector v1{10,20}, v2{30};// 高性能交換(無拷貝,僅交換指針)
    std::swap(v1, v2);  // v1: [30]|v2: [10,20](容量同步交換)
    
  • 值匹配刪除 erase() (C++20)

    std::vector nums{5,2,5,8};// 刪除所有值為5的元素 
    std::erase(nums, 5);  // 結果:[2,8](返回刪除數量)
    
  • 條件刪除 erase_if() (C++20)

    std::vector data{-3,7,-1,0};// 刪除所有負數(λ表達式)
    std::erase_if(data, [](int x){return x<0;});  // 結果:[7,0](支持復雜邏輯)
    

3. 操作對比總結

函數典型場景優勢
operator==配置比對/結果驗證深度比較容器內容
std::swap(vector&, vector&)線程安全數據交換零拷貝原子操作
erase(vector&, value)批量刪除特定值比循環+erase高效
erase_if(vector&, pred)復雜條件刪除(如負/奇數)避免手寫易出錯的迭代器邏輯

九、完整應用示例

1. 類對象的向量

  • 如果一個類類型的對象需要被存儲在向量中,那么這個類至少應該支持無參構造,以確保為這個向量所分配的內存能夠被正確的初始化。
  • 該類可能還需要支持拷貝構造函數和拷貝賦值操作符重載函數。
  • 如有必要可能還需要支持“==”和“<“操作符。
// 類對象的向量
#include <iostream>
#include <vector>using namespace std;class Integer {
public:Integer (void) : m_data (0) {cout << "無參構造:" << this << endl;}Integer (int data) : m_data (data) {cout << "有參構造:" << this << endl;}~Integer (void) {cout << "析構函數:" << this << endl;}Integer (const Integer& that) :m_data (that.m_data) {cout << "拷貝構造:" << &that << " -> " <<this << endl;}Integer& operator= (const Integer& that) {cout << "拷貝賦值:" << &that << " -> " <<this << endl;if (&that != this)m_data = that.m_data;return *this;}bool operator== (const Integer& that) const {return m_data == that.m_data;}bool operator< (const Integer& that) const {return m_data > that.m_data;}int m_data;
};int main (void) {cout << "-------- 1 --------" << endl;vector<Integer> vi (5, Integer (100));//1次有參構造 5次拷貝構造   6次析構cout << "-------- 2 --------" << endl;vi.erase (vi.begin ());               //刪除節點后元素前移 //4次拷貝賦值 5次析構  cout << "-------- 3 --------" << endl;vi.insert (vi.begin (), Integer (200));//插入節點后元素后移 //1次有參構造 1次拷貝構造 4次拷貝賦值 6次析構  cout << "-------- 4 --------" << endl;vi.resize (1);                         //調整容器大小為1   //5 次析構  cout << "-------- 5 --------" << endl;vi.resize (5);                         //調整容器大小為5   //5 次析構  cout << vi.capacity() << endl;         //5cout << "-------- 6 --------" << endl;vi.reserve (10);                       //調整容器大小為 10  //5次拷貝構造 添加5個初始化的0元素cout << "-------- X --------" << endl;vi[0] = 12;                            //分別調用5次 有參構造 拷貝賦值 析構函數:vi[1] = 23;vi[2] = 47;vi[3] = 33;vi[4] = 47;return 0;
}

2. 通過數組初始化向量

  • 核心代碼:vector<int> v1(&arr[0], &arr[5]);

    int arr[5] = {1, 2, 3, 4, 5};
    vector<int> v1 (&arr[0], &arr[5]);
    
  • 迭代器范圍原理:

    • &arr[0] 指向首元素(包含)

    • &arr[5] 是尾后指針(不包含)

    • 實際構造范圍:[arr[0], arr[5]) → 等價于 arr[0]到arr[4]

      // 用容器初始化容器
      #include <iostream>
      #include <vector>
      using namespace std;
      int main (void) {int arr[5] = {1, 2, 3, 4, 5};vector<int> v1 (&arr[0], &arr[5]);//實際構造范圍:[arr[0], arr[5]) → 等價于 arr[0]到arr[4]for (int i = 0; i < v1.size (); i++)cout << v1[i] << ' ';cout << endl;               // 1 2 3 4 5vector<int> v2 (v1.begin () + 1, v1.end () - 1);for (int i = 0; i < v2.size (); i++)cout << v2[i] << ' ';cout << endl;               // 2 3 4for (vector<int>::reverse_iterator it = v1.rbegin (); it != v1.rend (); it++)cout << *it << ' ';         // 5 4 3 2 1cout << endl;return 0;
      }
      

十、關鍵特性

  1. 動態內存管理:自動擴容(通常按2倍擴容)
  2. 連續存儲:支持指針算術操作
  3. 異常安全:強異常保證(部分操作)
  4. 時間復雜度:
    • 隨機訪問:O(1)
    • 尾部插入/刪除:均攤O(1)
    • 中間插入/刪除:O(n)

十一、應用注意事項??

1. 完美轉發陷阱

std::vector<std::unique_ptr<Device>> devices;
// 錯誤:嘗試復制 unique_ptr 
// devices.emplace_back(new Device()); // 正確:顯式移動 
devices.emplace_back(std::make_unique<Device>());

2. 高性能尾部操作

vector<int> data;
data.reserve(1000);  // 預分配避免多次擴容
for(int i=0; i<1000; ++i) 
data.emplace_back(i);// C++20 安全刪除
erase_if(data, [](int x){ return x%2==0; });

3. 內存釋放替代方案

// 強制釋放內存的可靠方法 
std::vector<int> huge_data = get_data();
std::vector<int>(huge_data).swap(huge_data);  // 通過臨時對象交換 

4. 函數選擇指南

場景推薦操作理論依據
容器狀態檢測empty()替代size()==0語義更清晰
高性能批量插入reserve()預分配避免多次擴容開銷
內存敏感型系統shrink_to_fit()減少內存占用(可能有效)
跨平臺開發避免依賴max_size()不同系統差異過大
實時系統慎用動態擴容防止不可預測的內存分配延遲

5. 避免裸指針操作

// 改用data()獲取首元素指針 
vector<int> v{1,2,3};
int* p = v.data();   // 等效&v[0]但更安全 

實際開發中,優先使用 emplace_back() 替代 push_back() 避免拷貝,結合 reserve() 可顯著提升性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93236.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93236.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93236.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

GPT-5系列文章2——新功能、測試與性能基準全解析

引言 2025年8月&#xff0c;OpenAI正式發布了其新一代旗艦模型GPT-5。與業界此前期待的AGI(人工通用智能)突破不同&#xff0c;GPT-5更像是OpenAI對現有技術的一次深度整合與用戶體驗優化。本文將全面解析GPT-5的新特性、實際測試表現以及官方發布的基準數據&#xff0c;幫助開…

利用cursor+MCP實現瀏覽器自動化釋放雙手

小伙伴們&#xff0c;我們今天利用cursorMCP實現瀏覽器自動化&#xff0c;釋放雙手&#xff0c;工作效率嘎嘎提升&#xff01;前期準備&#xff1a;安裝node.js網址&#xff1a;https://nodejs.org/zh-cn下載下來安裝即可。 下載browser-tools-mcp擴展程序&#xff1a;下載擴展…

指針/邊界索引混淆梳理

在處理數組/鏈表等數據結構時&#xff0c;時常混淆長度和指針序號。處理技巧&#xff1a;使用0-base索引。則區間長度 rightIndex - LeftIndex 1總長度 lastIndex - firstIndex 1鏈表創建一個dummy節點&#xff0c;添加到head前&#xff0c;則可認為從索引0開始。末尾指針判…

LeetCode 刷題【43. 字符串相乘】

43. 字符串相乘 自己做 解1&#xff1a;矩陣計數 class Solution { public:string multiply(string num1, string num2) {int len1 num1.size();int len2 num2.size();if (num1[0] 0 || num2[0] 0) //結果為0的情況return "0";//存儲計算過程的矩陣vector…

NLP數據增強方法及實現-A

目錄 詞替換 主要參考&#xff1a;paddlenlp/data_aug模塊 詞替換數據增強策略也即將句子中的詞隨機替換為其他單詞進行數據增強&#xff0c;這里我們將介紹如何使用paddlenlp.dataaug.WordSubstitute進行詞級別替換的數據增強。 WordSubstitute 參數介紹&#xff1a;aug_ty…

EhViewer安卓ios全版本類下載安裝工具的完整路徑解析

開發一款類似EhViewer的下載安裝工具&#xff08;集下載管理、應用部署等功能于一體&#xff09;&#xff0c;需要經歷從需求錨定到落地發布的系統性流程。以下從需求拆解到技術落地的全維度指南&#xff0c;將幫你理清開發脈絡&#xff0c;避開常見陷阱。安裝 GitHub - huangy…

MySQL 主鍵詳解:作用與使用方法

在 MySQL 數據庫中&#xff0c;主鍵&#xff08;Primary Key&#xff09; 是表結構設計中最重要的約束之一。它不僅是數據唯一性的保障&#xff0c;也是多表關聯、查詢優化的核心工具。本文將從 主鍵的作用 和 主鍵的用法 兩個方面進行講解&#xff0c;并配合代碼示例幫助理解一…

lib.dom.d.ts

lib.dom.d.ts 是一個 TypeScript 類型聲明文件&#xff0c;它是 TypeScript 標準庫的一部分&#xff0c;用于定義瀏覽器 DOM&#xff08;文檔對象模型&#xff09;相關的類型和接口。這個文件為開發者提供了瀏覽器中所有內置的 DOM 類型的定義&#xff0c;包括 localStorage、d…

Spring 工具類:StopWatch

StopWatch 是 Spring 框架提供的一個簡單而強大的計時工具類&#xff0c;用于測量代碼塊的執行時間。它特別適合在開發階段進行性能分析、調試和優化。 基本使用方法 // 創建 StopWatch 實例&#xff08;可指定 ID&#xff09; StopWatch stopWatch new StopWatch("性能分…

解決 VSCode 運行 Python 時 ModuleNotFoundError: No module named ‘open_webui‘ 問題

目錄 1. 問題原因分析 2. 解決思路 3. 解決步驟 3.1 打開或創建 .vscode/launch.json 3.2 添加調試配置 3.3 配置說明 3.4 運行測試 4. 總結 在使用 VSCode 調試 Python 項目時&#xff0c;我們經常會遇到類似下面的錯誤&#xff1a; Exception has occurred: ModuleN…

Python基礎-數據結構

數據結構 Python提供了四種主要的內置數據結構&#xff1a;列表&#xff08;List&#xff09;、元組&#xff08;Tuple&#xff09;、字典&#xff08;Dictionary&#xff09;和集合&#xff08;Set&#xff09;。每種數據結構都有其特定的用途和特性。 Python數據結構概覽&…

NLP學習之Transformer(1)

初識 Transformer &#xff08;1&#xff09; 1.簡介 1.1主要特點&#xff1a; self-attention&#xff1a; 自注意力機制&#xff0c;Transformer的核心是自注意力機制&#xff0c;它允許模型在處理某個位置的輸入時&#xff0c;能夠直接與其他位置的輸入交互&#xff0c;而不…

C語言筆記6:C高級 part1

1.gcc 編譯器 編譯流程 預處理-》編譯》匯編》鏈接》 E 預處理的命令 S 編譯匯編代碼 -c匯編階段命令 -o 輸出對應的文件GDB調試工具2.作用域存儲分類// C高級部分知識多&#xff0c; 加上這周 我學的知識量有點爆炸。家里又有事情&#xff0c;這周末要回老家 爭取下周補齊吧。…

A12預裝app

在A12上預裝應用&#xff0c;出現了一個異常。在此記錄問題描述&#xff1a;在A12上預裝應用按照A13的預裝方案報錯&#xff0c;mk文件如下&#xff1a;LOCAL_PATH : $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS : optional LOCAL_MODULE : Tideen_PTT LOCAL_MODU…

termios 線程 poll epoll進化 二叉AVL紅黑樹

struct termios tio 是什么 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h>#define SERIAL_PORT "/dev/ttyS0" #define BUF_SIZE 256int main(v…

C++設計模式:類間關系

類封裝了數據和行為&#xff0c;是面向對象的重要組成部分&#xff0c;它是具有相同屬性、操作、關系的對象集合的總稱。在系統中&#xff0c;每個類都具有一定的職責&#xff0c;職責指的是類要完成什么樣子的功能&#xff0c;要承擔什么樣子的義務。一個類可以有多種職責&…

MSYS2+CMake配置C/C++開發環境

目錄一、MSYS2是什么1.1 核心架構與組件??1.1.1 背景介紹1.1.1.1 Cygwin1.1.1.2 MinGW和Mingw-w641.1.1.3MSYS和MSYS21.1.2 技術基礎??1.1.3 多環境支持??1.2 核心功能??1.2.1 類Unix開發環境??1.2.2 開發工具鏈??1.2.3 軟件倉庫與包管理??二、安裝和配置2.1 配置…

Vue 3 + TypeScript:package.json 示例 / 詳細注釋說明

一、示例 / 詳細注釋說明 {// 項目基礎信息"name": "vite-project", // 項目名稱&#xff08;建議使用 kebab-case 格式&#xff09;"private": true, // 標記為私有項目&#xff0c;避免意外發布到 npm"version": "1.0.…

SpatialVLM和SpatialRGPT論文解讀

目錄 一、SpatialVLM 1、概述 2、方法 3、實驗 二、SpatialRGPT 1、概述 2、方法 3、訓練方法 4、實驗 一、SpatialVLM 1、概述 SpatialVLM是最早的依賴傳統VLMs實現3D空間推理能力的論文&#xff0c;在24年1月由DeepMind團隊提出&#xff0c;當時對比的還是GPT4v&am…

理解GPU架構:基礎與關鍵概念

GPU 基礎概述&#xff1a;從圖形渲染到 AI 與高性能計算的核心 Graphics Processing Units&#xff08;GPU&#xff09;已從專用的圖形渲染硬件演進為 AI、科學計算與高性能任務的中堅力量。本文將介紹 GPU 架構的基礎知識&#xff0c;包括其組成部分、內存層次結構&#xff0c…