Stories

Detail Return Return

神奇的“維克托” - Stories Detail

**C++ 中  std::vector  全面解析(從基礎到進階)

 std::vector  是 C++ 標準庫(STL)中最常用的動態數組容器,能自動管理內存、動態擴容,比手動用  new[]  分配數組更安全高效,是日常開發的“高頻工具”。下面從基礎用法到進階技巧,帶你吃透它~**

一、基礎:怎麼用  std::vector ?

1. 頭文件與初始化

用  std::vector  前必須包含頭文件  <vector> ,初始化方式有多種,按需選擇:

cpp

include <vector>

include <iostream>

using namespace std; // 簡化代碼,實際項目建議少用

int main() {

// 1. 空向量(最常用,後續動態添加元素)
vector<int> vec1;

// 2. 初始化 5 個元素,每個元素值為 0
vector<int> vec2(5, 0); 

// 3. 用列表初始化(C++11 及以後支持)
vector<int> vec3 = {1, 2, 3, 4, 5}; 

// 4. 拷貝另一個向量
vector<int> vec4(vec3); 
return 0;

}
 

  1. 核心操作:增刪查改

cpp

vector<int> vec = {1, 2, 3};

// 1. 增加元素(尾插最高效,時間複雜度 O(1))
vec.push_back(4); // 結果:[1,2,3,4]
// C++11 後支持 emplace_back(直接在容器內構造元素,比 push_back 更高效)
vec.emplace_back(5); // 結果:[1,2,3,4,5]

// 2. 刪除元素(尾刪高效,O(1);刪除中間元素需移動數據,O(n))
vec.pop_back(); // 刪除最後一個元素,結果:[1,2,3,4]
// 刪除指定位置元素(用迭代器)
vec.erase(vec.begin() + 1); // 刪除索引 1 的元素(值為 2),結果:[1,3,4]

// 3. 訪問元素(3種方式)
cout << vec[0]; // 1(直接用索引,無越界檢查,快)
cout << vec.at(1); // 3(帶越界檢查,越界會拋異常,安全)
cout << vec.front(); // 1(訪問第一個元素)
cout << vec.back(); // 4(訪問最後一個元素)

// 4. 修改元素
vec[2] = 10; // 結果:[1,3,10]
 

  1. 常用屬性

cpp

vector<int> vec = {1,3,10};
cout << vec.size(); // 3(當前元素個數)
cout << vec.capacity(); // 3(當前容器能容納的最大元素數,未擴容時等於 size)
cout << vec.empty(); // false(判斷是否為空,空則返回 true)
vec.clear(); // 清空所有元素(size 變為 0,但 capacity 不變)
 

大標題

二、進階:理解  std::vector  的核心機制

大標題

  1. 動態擴容原理

 std::vector  底層是連續內存空間,當  push_back  元素超過當前  capacity  時,會觸發“擴容”:

分配一塊更大的新內存(通常是原容量的 2 倍,不同編譯器可能有差異,比如 VS 是 1.5 倍);

把原內存的元素拷貝/移動到新內存;

釋放原內存。

⚠️ **注意:擴容後,原有的迭代器、指針、引用會失效(因為內存地址變了),比如:

cpp

vector<int> vec = {1,2,3};
int* p = &vec[0]; // 指向第一個元素的指針
vec.push_back(4); // 若觸發擴容,p 會變成“野指針”,再用 p 訪問會出錯
 

2. 避免頻繁擴容:提前 reserve

大標題

如果知道大概要存多少元素,用  reserve(n)  提前分配  n  個容量,避免多次擴容(減少拷貝開銷):

cpp

vector<int> vec;
vec.reserve(100); // 提前分配 100 個容量,後續添加 100 個元素不會擴容
for (int i = 0; i < 100; i++) {

vec.push_back(i);

}
 

  1. 迭代器的使用(遍歷/操作)

迭代器是訪問容器的“通用指針”, std::vector  支持隨機訪問迭代器(可像指針一樣加減偏移):

cpp

vector<int> vec = {1,3,10};

// 1. 正向遍歷
for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {

cout << *it << " "; // 輸出:1 3 10

}

// 2. 反向遍歷(用 reverse_iterator)
for (vector<int>::reverse_iterator it = vec.rbegin(); it != vec.rend(); it++) {

cout << *it << " "; // 輸出:10 3 1

}

// 3. C++11 後簡化:範圍 for 循環(底層還是迭代器)
for (int num : vec) {

cout << num << " "; // 輸出:1 3 10

}
 

三、實戰: std::vector  的常見場景

  1. 存儲自定義類型

 std::vector  不僅能存int、string等基礎類型,還能存自定義結構體/類:

cpp

struct Student {

string name;
int age;

};

int main() {

vector<Student> stu_vec;
// 用 emplace_back 直接構造 Student 對象(高效)
stu_vec.emplace_back("張三", 18);
stu_vec.emplace_back("李四", 19);

// 遍歷輸出
for (auto& stu : stu_vec) { // 用 auto 簡化類型,& 避免拷貝
    cout << stu.name << " " << stu.age << endl;
}
return 0;

}
 

  1. 作為函數參數/返回值
  • 傳參:建議用引用(&) 或常量引用(const &),避免拷貝整個向量(尤其是數據量大時);
  • 返回值:C++11 後支持“移動語義”,直接返回向量不會有額外拷貝開銷,放心用:

cpp

// 常量引用傳參:只讀,不修改向量
void printVec(const vector<int>& vec) {

for (int num : vec) cout << num << " ";

}

// 直接返回向量(C++11+ 高效)
vector<int> getEvenNumbers(int n) {

vector<int> res;
for (int i = 0; i <= n; i += 2) {
    res.push_back(i);
}
return res;

}

int main() {

vector<int> even_vec = getEvenNumbers(10); // 得到 [0,2,4,6,8,10]
printVec(even_vec);
return 0;

}
 

四、注意事項

不支持在中間高效插入元素:因為底層是連續內存,中間插入需要移動後續所有元素,時間複雜度 O(n),如果需要頻繁中間插入,建議用  std::list ;

越界訪問風險:用  []  訪問時沒有越界檢查,Debug 階段可用  at()  或開啓編譯器越界檢查(如 GCC 的  -fsanitize=address );

清空元素不釋放內存: clear()  只會把  size  設為 0, capacity  不變,若想釋放內存,可藉助“臨時向量”的特性:

cpp

vector<int> vec = {1,2,3,4,5};
vec.clear(); // size=0,capacity=5
// 用臨時向量交換,釋放內存(capacity 會變成 0)
vector<int>().swap(vec);
 

 std::vector  是 C++ 開發的“基石工具”,掌握它的基礎用法、擴容原理和實戰技巧,能解決大部分動態數組場景的需求,日常開發中優先用它,而非手動管理數組~**

user avatar lizhuo6 Avatar itwhat Avatar youqingyouyidedalianmao Avatar puxiaoke6 Avatar zengjingaiguodekaomianbao Avatar xiaohuzideboluo_cvmeub Avatar aitigou Avatar ysxq Avatar zlibrarynew Avatar lyh_bxxw Avatar jianzhuangdeyaling Avatar manxisuo Avatar
Favorites 16 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.