C++ --vector

发布时间:2026/7/24 17:53:45
C++ --vector 1. 核心特点std::vector是动态数组元素在内存中连续存储支持随机访问能在尾部高效增删。2. 基本操作创建与初始化#include vector using namespace std; vectorint v1; // 空 vectorint v2(10); // 10个元素值初始化为0 vectorint v3(10, 5); // 10个5 vectorint v4 {1,2,3,4}; // 列表初始化 vectorint v5(v4); // 拷贝构造常用成员函数一、构造与赋值1. 默认构造vector()创建一个空的 vector没有任何元素。#include iostream #include vector using namespace std; int main() { vectorint v; // 默认构造空容器 cout size v.size() endl; // 输出: 0 cout empty v.empty() endl; // 输出: 1 (true) return 0; }2. 指定大小构造vector(n)和vector(n, val)vector(n)创建 n 个元素值初始化为 0对 int 来说。vector(n, val)创建 n 个元素都初始化为 val。#include iostream #include vector using namespace std; int main() { vectorint v1(5); // 5个元素默认初始化为0 vectorint v2(5, 10); // 5个元素都初始化为10 cout v1: ; for (int x : v1) cout x ; // 输出: 0 0 0 0 0 cout endl; cout v2: ; for (int x : v2) cout x ; // 输出: 10 10 10 10 10 cout endl; return 0; }3. 列表初始化vector(initializer_list)用花括号直接初始化最直观的方式。#include iostream #include vector using namespace std; int main() { vectorint v {1, 2, 3, 4, 5}; // 列表初始化 // 或者 vectorint v{1, 2, 3, 4, 5}; cout 元素: ; for (int x : v) cout x ; // 输出: 1 2 3 4 5 cout endl; cout size v.size() endl; // 输出: 5 return 0; }4. 拷贝构造vector(const vector)#include iostream #include vector using namespace std; int main() { vectorint v1 {1, 2, 3, 4, 5}; // 拷贝构造 vectorint v2(v1); // 深拷贝v1 和 v2 独立 v2.push_back(6); cout v1: ; for (int x : v1) cout x ; // 输出: 1 2 3 4 5 cout endl; cout v2: ; for (int x : v2) cout x ; // 输出: 1 2 3 4 5 6 cout endl; return 0; }5. 赋值operator和assign()operator赋值清空原内容并拷贝新内容。assign()重新赋值可以指定数量和值或迭代器区间。#include iostream #include vector using namespace std; int main() { vectorint v1 {1, 2, 3}; vectorint v2 {4, 5, 6, 7}; // operator v1 v2; // v1 变成 {4, 5, 6, 7} cout v1 v2 后: ; for (int x : v1) cout x ; // 输出: 4 5 6 7 cout endl; // assign清空并重新赋值 v1.assign(3, 100); // 3个100 cout v1.assign(3, 100) 后: ; for (int x : v1) cout x ; // 输出: 100 100 100 cout endl; // assign 用迭代器区间 v2.assign(v1.begin(), v1.end()); // v2 变成 {100, 100, 100} cout v2 变成: ; for (int x : v2) cout x ; cout endl; return 0; }二、容量相关6.size()和capacity()size()当前元素个数。capacity()当前已分配内存能容纳的元素个数总是 size。#include iostream #include vector using namespace std; int main() { vectorint v; cout 初始: size v.size() , capacity v.capacity() endl; // 输出: 初始: size0, capacity0 v.push_back(1); cout push 1 后: size v.size() , capacity v.capacity() endl; // 可能输出: push 1 后: size1, capacity1 v.push_back(2); v.push_back(3); cout push 3 个后: size v.size() , capacity v.capacity() endl; // 可能输出: push 3 个后: size3, capacity4 (容量可能翻倍) return 0; }7.empty()判断容器是否为空比size() 0更高效O(1)。#include iostream #include vector using namespace std; int main() { vectorint v; if (v.empty()) { cout v 是空的 endl; // 输出这行 } v.push_back(42); if (!v.empty()) { cout v 现在有 v.size() 个元素 endl; // 输出: v 现在有 1 个元素 } return 0; }8.reserve(n)预分配至少 n 个元素的空间只改变 capacity不改变 size。用途提前知道元素数量时避免多次扩容。#include iostream #include vector using namespace std; int main() { vectorint v; v.reserve(100); // 提前分配 100 个元素的空间 cout reserve(100) 后: size v.size() , capacity v.capacity() endl; // 输出: reserve(100) 后: size0, capacity100 for (int i 0; i 100; i) { v.push_back(i); // 这 100 次 push 不会触发扩容 } cout 插入 100 个元素后: size v.size() , capacity v.capacity() endl; // 输出: 插入 100 个元素后: size100, capacity100 return 0; }9.resize(n)和resize(n, val)改变 size 为 n如果 n 当前 size尾部新增元素用默认值或 val 填充如果 n 当前 size尾部删除元素#include iostream #include vector using namespace std; int main() { vectorint v {1, 2, 3, 4, 5}; cout 初始: ; for (int x : v) cout x ; // 输出: 1 2 3 4 5 cout , size v.size() endl; // resize 变大用默认值填充 v.resize(8); cout resize(8) 后: ; for (int x : v) cout x ; // 输出: 1 2 3 4 5 0 0 0 cout , size v.size() endl; // resize 变大用指定值填充 v.resize(10, 99); cout resize(10, 99) 后: ; for (int x : v) cout x ; // 输出: 1 2 3 4 5 0 0 0 99 99 cout , size v.size() endl; // resize 变小删除尾部元素 v.resize(3); cout resize(3) 后: ; for (int x : v) cout x ; // 输出: 1 2 3 cout , size v.size() endl; return 0; }10.shrink_to_fit()请求将 capacity 缩小到刚好等于 size释放多余内存。这是非强制请求实现可能忽略。#include iostream #include vector using namespace std; int main() { vectorint v; v.reserve(1000); for (int i 0; i 10; i) v.push_back(i); cout 添加 10 个元素后: size v.size() , capacity v.capacity() endl; // 输出: 添加 10 个元素后: size10, capacity1000 v.shrink_to_fit(); // 请求缩容 cout shrink_to_fit 后: size v.size() , capacity v.capacity() endl; // 输出: shrink_to_fit 后: size10, capacity10 (可能) return 0; }三、元素访问11.operator[](idx)和at(idx)两者都通过下标访问元素。operator[]无边界检查性能更高越界是未定义行为。at()有边界检查越界抛出std::out_of_range异常。#include iostream #include vector using namespace std; int main() { vectorint v {10, 20, 30, 40, 50}; // operator[] - 无检查 cout v[0] v[0] endl; // 输出: 10 cout v[2] v[2] endl; // 输出: 30 v[1] 99; // 修改 cout 修改后 v[1] v[1] endl; // 输出: 99 // at() - 有检查 try { cout v.at(0) v.at(0) endl; // 输出: 10 cout v.at(10) v.at(10) endl; // 越界抛异常 } // 危险operator[] 越界不会报错未定义行为 // cout v[100] endl; // 不能这样写 return 0; }12.front()和back()访问第一个和最后一个元素的引用。空容器调用是未定义行为。#include iostream #include vector using namespace std; int main() { vectorint v {1, 2, 3, 4, 5}; cout 第一个元素: v.front() endl; // 输出: 1 cout 最后一个元素: v.back() endl; // 输出: 5 // 可以修改 v.front() 100; v.back() 200; cout 修改后: ; for (int x : v) cout x ; // 输出: 100 2 3 4 200 cout endl; // 注意空容器调用 front/back 是未定义行为 vectorint empty; // cout empty.front() endl; // 不要这样写 return 0; }13.data()返回指向底层数组的指针。#include iostream #include vector using namespace std; int main() { vectorint v {1, 2, 3, 4, 5}; int* p v.data(); // 获取底层数组指针 cout 通过指针访问: ; for (size_t i 0; i v.size(); i) { cout p[i] ; // 输出: 1 2 3 4 5 } cout endl; // 修改也能反映到 vector p[0] 99; cout 修改后 v[0] v[0] endl; // 输出: 99 return 0; }四、增删操作14.push_back(val)和pop_back()尾部插入和尾部删除都是高效操作均摊 O(1)。#include iostream #include vector using namespace std; int main() { vectorint v; // push_back 尾部插入 v.push_back(10); v.push_back(20); v.push_back(30); cout push 3 个后: ; for (int x : v) cout x ; // 输出: 10 20 30 cout , size v.size() endl; // pop_back 尾部删除 v.pop_back(); // 删除 30 cout pop 一个后: ; for (int x : v) cout x ; // 输出: 10 20 cout , size v.size() endl; // pop_back 不返回元素想获取尾部元素用 back() if (!v.empty()) { int last v.back(); v.pop_back(); cout 删除了最后一个元素: last endl; // 输出: 20 } return 0; }15.emplace_back( )尾部就地构造元素避免临时对象产生比 push_back 更高效。#include iostream #include vector #include string using namespace std; struct Person { string name; int age; Person(string n, int a) : name(n), age(a) { cout 构造: name endl; } }; int main() { vectorPerson v; cout 使用 push_back: endl; v.push_back(Person(张三, 25)); // 先构造临时对象再拷贝到 vector cout endl; cout 使用 emplace_back: endl; v.emplace_back(李四, 30); // 直接在 vector 内部构造无临时对象 cout endl; // 对于基本类型emplace_back 和 push_back 差不多 vectorint vi; vi.emplace_back(42); // 相当于 push_back(42) return 0; }16.insert(pos, val)和insert(pos, n, val)在指定位置插入元素单个或多个会移动后续元素时间复杂度 O(n)。#include iostream #include vector using namespace std; int main() { vectorint v {1, 2, 4, 5}; cout 初始: ; for (int x : v) cout x ; // 输出: 1 2 4 5 cout endl; // 在 begin()2 位置插入 3 auto it v.insert(v.begin() 2, 3); cout 插入 3 后: ; for (int x : v) cout x ; // 输出: 1 2 3 4 5 cout , 插入位置指向: *it endl; // 返回指向新元素的迭代器 // 在 begin()1 位置插入 3 个 99 v.insert(v.begin() 1, 3, 99); cout 插入 3 个 99 后: ; for (int x : v) cout x ; // 输出: 1 99 99 99 2 3 4 5 cout endl; return 0; }17.emplace(pos, args...)在指定位置就地构造元素比 insert 更高效。#include iostream #include vector #include string using namespace std; struct Person { string name; int age; Person(string n, int a) : name(n), age(a) {} }; int main() { vectorPerson v; v.emplace_back(张三, 25); v.emplace_back(王五, 35); // 在 begin()1 位置就地构造 auto it v.emplace(v.begin() 1, 李四, 30); cout 插入后: endl; for (const auto p : v) { cout p.name ( p.age 岁) endl; } // 输出: // 张三 (25岁) // 李四 (30岁) // 王五 (35岁) return 0; }18.erase(pos)和erase(first, last)删除单个元素或区间元素会移动后续元素时间复杂度 O(n)。返回指向被删元素之后元素的迭代器。#include iostream #include vector using namespace std; int main() { vectorint v {10, 20, 30, 40, 50, 60, 70}; cout 初始: ; for (int x : v) cout x ; // 输出: 10 20 30 40 50 60 70 cout endl; // 删除单个元素位置 3即 40 auto it v.erase(v.begin() 3); cout 删除 40 后: ; for (int x : v) cout x ; // 输出: 10 20 30 50 60 70 cout , 返回的迭代器指向: *it endl; // 输出: 50 // 删除区间 [begin()1, begin()3)即删除 20, 30 it v.erase(v.begin() 1, v.begin() 3); cout 删除 20,30 后: ; for (int x : v) cout x ; // 输出: 10 50 60 70 cout , 返回的迭代器指向: *it endl; // 输出: 50 // 常见用法删除所有偶数 vectorint v2 {1, 2, 3, 4, 5, 6, 7, 8}; for (auto it2 v2.begin(); it2 ! v2.end(); ) { if (*it2 % 2 0) { it2 v2.erase(it2); // erase 返回下一个有效迭代器 } else { it2; } } cout 删除偶数后: ; for (int x : v2) cout x ; // 输出: 1 3 5 7 cout endl; return 0; }19.clear()删除所有元素size 变为 0但 capacity 通常不变内存不释放。#include iostream #include vector using namespace std; int main() { vectorint v {1, 2, 3, 4, 5}; cout 清空前: size v.size() , capacity v.capacity() endl; // 输出: 清空前: size5, capacity5 v.clear(); cout 清空后: size v.size() , capacity v.capacity() endl; // 输出: 清空后: size0, capacity5 (capacity 不变) cout 是否为空: (v.empty() ? 是 : 否) endl; // 输出: 是 // 如果也想释放内存用 shrink_to_fit 或 swap vectorint().swap(v); // 彻底释放内存 return 0; }20.swap(v2)交换两个 vector 的内容O(1) 时间只交换内部指针。#include iostream #include vector using namespace std; int main() { vectorint v1 {1, 2, 3, 4, 5}; vectorint v2 {10, 20, 30}; cout 交换前: endl; cout v1: ; for (int x : v1) cout x ; // 输出: 1 2 3 4 5 cout endl; cout v2: ; for (int x : v2) cout x ; // 输出: 10 20 30 cout endl; v1.swap(v2); // 交换内容 cout 交换后: endl; cout v1: ; for (int x : v1) cout x ; // 输出: 10 20 30 cout endl; cout v2: ; for (int x : v2) cout x ; // 输出: 1 2 3 4 5 cout endl; // 释放内存 vectorint v3 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cout v3 清空前: size v3.size() , capacity v3.capacity() endl; vectorint().swap(v3); // 清空并释放内存 cout v3 清空后: size v3.size() , capacity v3.capacity() endl; return 0; }五、迭代器 迭代器的基本知识21.begin()/end()和cbegin()/cend()获取迭代器用于遍历。begin()返回普通迭代器cbegin()返回 const 迭代器。#include iostream #include vector using namespace std; int main() { vectorint v {10, 20, 30, 40, 50}; // 正向遍历 cout 正向遍历: ; for (auto it v.begin(); it ! v.end(); it) { cout *it ; // 输出: 10 20 30 40 50 } cout endl; // 使用 const 迭代器不能修改 cout const 迭代器: ; for (auto it v.cbegin(); it ! v.cend(); it) { cout *it ; // 输出: 10 20 30 40 50 // *it 100; // 错误不能通过 const 迭代器修改 } cout endl; // 范围 for 本质上也是用 begin/end cout 范围 for: ; for (int x : v) cout x ; cout endl; return 0; }六、比较运算符22., !, , , , 按字典序比较两个 vector 的元素。#include iostream #include vector using namespace std; int main() { vectorint v1 {1, 2, 3, 4, 5}; vectorint v2 {1, 2, 3, 4, 5}; vectorint v3 {1, 2, 3, 4, 6}; vectorint v4 {1, 2, 3}; cout v1 v2: (v1 v2) endl; // 输出: 1 (true) cout v1 v3: (v1 v3) endl; // 输出: 0 (false) cout v1 v3: (v1 v3) endl; // 输出: 1 (true, 56) cout v1 v4: (v1 v4) endl; // 输出: 0 (false, 前3个相等但v1更长) cout v4 v1: (v4 v1) endl; // 输出: 1 (true, v4是v1的前缀) return 0; }动态二维数组的理解一、什么是动态二维数组静态二维数组在编译时就要确定大小比如int arr[3][4]。动态二维数组在运行时才确定行数和列数可以根据需要动态调整。#include iostream using namespace std; int main() { int rows, cols; cout 请输入行数和列数: ; cin rows cols; // 静态数组做不到编译时就要知道大小 // int arr[rows][cols]; // 错误 // 动态二维数组可以在运行时确定大小 // 需要动态分配内存... return 0; }二、为什么需要动态二维数组场景1数据量不确定// 读取用户输入的数据不知道有多少行 vectorvectorint data; int value; while (cin value) { data.push_back({value}); // 动态增加行 }场景2每行长度不同// 三角形矩阵第 i 行有 i1 个元素 int n 5; vectorvectorint triangle(n); for (int i 0; i n; i) { triangle[i].resize(i 1); // 每行长度不同 }场景3程序运行时才知道大小// 图像处理读入图片才知道尺寸 int width, height; readImageSize(width, height); int** p new int*[height]; for (int i 0; i height; i) { p[i] new int[width]; }三、使用vectorvectorT实现动态二维数组原理外层 vector 的每个元素是一个 vector每个内层 vector 独立管理自己的内存。#include iostream #include vector using namespace std; int main() { int rows 3, cols 4; // 创建 3x4 的二维数组所有元素初始化为 0 vectorvectorint matrix(rows, vectorint(cols, 0)); // 赋值 for (int i 0; i rows; i) { for (int j 0; j cols; j) { matrix[i][j] i * cols j; } } // 遍历 cout 矩阵内容 endl; for (int i 0; i rows; i) { for (int j 0; j cols; j) { cout matrix[i][j] \t; } cout endl; } // 输出 // 0 1 2 3 // 4 5 6 7 // 8 9 10 11 // 每行可以有不同的长度 vectorvectorint jagged(3); jagged[0] {1, 2, 3}; jagged[1] {4, 5}; jagged[2] {6, 7, 8, 9}; cout \n endl; for (int i 0; i jagged.size(); i) { cout 第 i 行有 jagged[i].size() 个元素: ; for (int x : jagged[i]) cout x ; cout endl; } return 0; }内存布局matrix (vector对象) └── [vectorint] ──→ [0][1][2][3] (连续内存) └── [vectorint] ──→ [4][5][6][7] (连续内存) └── [vectorint] ──→ [8][9][10][11] (连续内存) ↑ 每行内存独立不一定连续