Ch 14: std::vector 详解
- 熟练使用 std::vector 的各种构造和初始化方式
- 掌握迭代器的使用和运算
- 理解 vector 的容量管理和内存分配策略
- 学会避免迭代器失效的常见陷阱
- 理解 emplace vs push 的性能差异
14.1 Python list vs C++ vector 对比
Section titled “14.1 Python list vs C++ vector 对比”Python list 回顾
Section titled “Python list 回顾”# Python - 动态列表,操作直观numbers = [1, 2, 3, 4, 5]
# 添加元素numbers.append(6) # [1, 2, 3, 4, 5, 6]numbers.insert(0, 0) # [0, 1, 2, 3, 4, 5, 6]numbers.extend([7, 8]) # [0, 1, 2, 3, 4, 5, 6, 7, 8]
# 访问 - 切片是 Python 特有功能x = numbers[0] # 第一个y = numbers[-1] # 最后一个z = numbers[2:5] # 切片 [3, 4, 5]sliced = numbers[::2] # 步长 [0, 2, 4, 6, 8]
# 删除numbers.pop() # 删除最后一个,返回值numbers.pop(0) # 删除第一个del numbers[3] # 删除指定位置numbers.remove(3) # 删除第一个出现的值
# 列表推导squares = [x**2 for x in range(10)]evens = [x for x in range(20) if x % 2 == 0]C++ vector 基础
Section titled “C++ vector 基础”#include <vector>#include <iostream>
int main() { // 构造方式 std::vector<int> v1; // 空 vector std::vector<int> v2(5); // 5 个元素,值初始化为 0 std::vector<int> v3(5, 10); // 5 个元素,每个都是 10 std::vector<int> v4 = {1, 2, 3, 4, 5}; // 初始化列表 std::vector<int> v5(v4); // 拷贝构造 std::vector<int> v6(std::move(v4)); // 移动构造
// 添加元素 v1.push_back(1); v1.push_back(2); v1.emplace_back(3); // C++11 原位构造,更高效
// 访问 int x = v1[0]; // 第一个(不检查边界) int y = v1.at(0); // 第一个(带边界检查) int z = v1.front(); // 第一个 int w = v1.back(); // 最后一个
// 大小 std::size_t size = v1.size(); // 元素个数 bool empty = v1.empty(); // 是否为空
// 删除 v1.pop_back(); // 删除最后一个 v1.clear(); // 清空所有
return 0;}| 特性 | Python list | C++ vector |
|---|---|---|
| 切片操作 | list[1:3] | 需要用 vector + erase 或 std::vector<int> 子范围 |
| 负索引 | list[-1] | 用 v.back() 或 v[v.size()-1] |
| 自动扩容 | 是 | 是(但需要手动调用 reserve 优化) |
| 类型检查 | 运行时 | 编译时 |
| 内存管理 | 全自动 | 半自动(自动析构,手动 shrink_to_fit) |
14.2 vector 的构造和初始化
Section titled “14.2 vector 的构造和初始化”各种构造方式详解
Section titled “各种构造方式详解”#include <vector>#include <iostream>#include <string>
int main() { // 1. 默认构造 - 空 vector std::vector<int> empty; std::cout << "empty.size() = " << empty.size() << std::endl; // 0
// 2. 构造 n 个元素(值初始化) std::vector<int> five_zeros(5); // {0, 0, 0, 0, 0} std::vector<std::string> five_empty_strings(5); // 5 个空 string
// 3. 构造 n 个相同元素 std::vector<int> five_tens(5, 10); // {10, 10, 10, 10, 10} std::vector<std::string> five_hellos(3, "hello"); // {"hello", "hello", "hello"}
// 4. 初始化列表(C++11) std::vector<int> numbers = {1, 2, 3, 4, 5}; std::vector<std::string> words = {"apple", "banana", "cherry"};
// 5. 从另一个 vector 拷贝 std::vector<int> copy(numbers); // 完整拷贝 std::vector<int> copy2 = numbers; // 同上
// 6. 从迭代器范围构造(C++11) std::vector<int> from_range(numbers.begin(), numbers.begin() + 3); // {1, 2, 3}
// 7. 移动构造(C++11) std::vector<int> source = {1, 2, 3}; std::vector<int> moved(std::move(source)); // source 变为空 // source 现在是空 vector!
// 8. C++17 从数组 int arr[] = {1, 2, 3, 4, 5}; std::vector<int> from_array(std::begin(arr), std::end(arr));
// 9. 构造并指定分配器(很少用) std::vector<int, std::allocator<int>> with_alloc;
return 0;}初始化 vs 赋值
Section titled “初始化 vs 赋值”#include <vector>
int main() { // 列表初始化(花括号)- 优先使用 std::vector<int> v1 = {1, 2, 3}; // 列表初始化 std::vector<int> v2{1, 2, 3}; // 同上(但注意窄化转换)
// 注意:窄化转换问题 double d = 3.14; // std::vector<int> v3{d}; // ❌ 错误!double 不能窄化为 int std::vector<int> v3{static_cast<int>(d)}; // OK
// 圆括号构造 std::vector<int> v4(5, 10); // {10, 10, 10, 10, 10} std::vector<int> v5(5); // {0, 0, 0, 0, 0} - 值初始化
// 陷阱:区分 1 个元素和 1, 2, 3 std::vector<int> v6{10}; // 1 个元素:10 std::vector<int> v7(10); // 10 个元素:0, 0, 0, ...(值初始化)
return 0;}14.3 元素访问
Section titled “14.3 元素访问”安全访问方式
Section titled “安全访问方式”#include <vector>#include <iostream>#include <stdexcept>
int main() { std::vector<int> v = {10, 20, 30, 40, 50};
// 1. 下标访问(不检查边界,最快) int first = v[0]; // 10 int last = v[v.size() - 1]; // 50 // v[100] // ❌ 未定义行为!
// 2. at() 访问(带边界检查) int second = v.at(1); // 20 // v.at(100) // ❌ 抛出 std::out_of_range
// 3. front() 和 back() int& front = v.front(); // 10 int& back = v.back(); // 50 front = 100; // v 现在是 {100, 20, 30, 40, 50}
// 4. data() - 返回底层数组指针 int* ptr = v.data(); std::cout << "First element: " << *ptr << std::endl; // 100
// 5. 迭代器访问(见下一节) auto it = v.begin(); int third = *(it + 2); // 30
// 安全检查 if (!v.empty()) { // 此时可以安全访问 std::cout << v.front() << " " << v.back() << std::endl; }
return 0;}Python 切片 vs C++ 子范围
Section titled “Python 切片 vs C++ 子范围”# Python - 切片numbers = [10, 20, 30, 40, 50]subset = numbers[1:4] # [20, 30, 40]reversed = numbers[::-1] # [50, 40, 30, 20, 10]#include <vector>#include <iostream>#include <algorithm>
int main() { std::vector<int> v = {10, 20, 30, 40, 50};
// C++ - 没有内置切片,需要用算法 // 取子范围 [1:4] std::vector<int> subset(v.begin() + 1, v.begin() + 4); // {20, 30, 40}
// 反向(手动) std::vector<int> reversed(v.rbegin(), v.rend()); // {50, 40, 30, 20, 10}
// C++20 可以用 views #include <ranges> auto view = v | std::views::drop(1) | std::views::take(3); // {20, 30, 40}
return 0;}14.4 迭代器详解
Section titled “14.4 迭代器详解”基本迭代器操作
Section titled “基本迭代器操作”#include <vector>#include <iostream>
int main() { std::vector<int> v = {10, 20, 30, 40, 50};
// begin() 和 end() for (auto it = v.begin(); it != v.end(); ++it) { std::cout << *it << " "; // 10 20 30 40 50 } std::cout << std::endl;
// cbegin() 和 cend() - const 迭代器 for (auto it = v.cbegin(); it != v.cend(); ++it) { // *it 是 const,不能修改 std::cout << *it << " "; } std::cout << std::endl;
// rbegin() 和 rend() - 反向迭代器 for (auto it = v.rbegin(); it != v.rend(); ++it) { std::cout << *it << " "; // 50 40 30 20 10 } std::cout << std::endl;
// crbegin() 和 crend() - const 反向迭代器 for (auto it = v.crbegin(); it != v.crend(); ++it) { std::cout << *it << " "; } std::cout << std::endl;
return 0;}迭代器算术运算
Section titled “迭代器算术运算”#include <vector>#include <iostream>
int main() { std::vector<int> v = {10, 20, 30, 40, 50};
auto it = v.begin(); // 指向 10
// 前进/后退 auto it2 = it + 2; // 指向 30 auto it3 = it2 - 1; // 指向 20
// 距离 std::ptrdiff_t dist = v.end() - v.begin(); // 5
// 比较 if (it2 > it) std::cout << "it2 is after it\n";
// 解引用 int val = *it2; // 30 int val2 = it2[2]; // 50(偏移 2) int val3 = *(it2 + 2); // 50(等价于 it2[2])
// += 和 -= auto it4 = v.begin(); it4 += 3; // 指向 40 it4 -= 2; // 指向 20
// 前置/后置递增 auto it5 = v.begin(); ++it5; // 前置递增(推荐,更高效) it5++; // 后置递增
return 0;}迭代器失效的情况
Section titled “迭代器失效的情况”#include <vector>#include <iostream>
int main() { std::vector<int> v = {1, 2, 3, 4, 5};
// ❌ 危险:添加元素后迭代器可能失效 auto it = v.begin() + 2; // 指向 3 std::cout << "Before insert: *it = " << *it << std::endl;
v.insert(v.begin(), 0); // 插入可能导致重新分配
// it 现在是悬空迭代器!使用它是未定义行为! // std::cout << "After insert: *it = " << *it << std::endl; // ❌
// ✅ 正确做法:在修改后重新获取迭代器 it = v.begin() + 3; // 重新获取 std::cout << "After re-get: *it = " << *it << std::endl; // 3
// ❌ 危险:删除元素后 it = v.begin() + 2; // 指向 3 v.erase(v.begin()); // 删除第一个元素
// it 仍然指向原来的内存位置,但数据可能已移动 // std::cout << *it << std::endl; // ❌ 危险!
return 0;}安全修改 vector 的方式
Section titled “安全修改 vector 的方式”#include <vector>#include <algorithm>#include <iostream>
int main() { std::vector<int> v = {1, 2, 3, 4, 5};
// ✅ 安全方式 1:用索引代替迭代器 for (std::size_t i = 0; i < v.size(); ++i) { if (v[i] == 3) { v.push_back(100); // 安全(不会在循环中触发 realloc) } }
// ✅ 安全方式 2:先记录要修改的位置 std::vector<std::size_t> positions_to_modify; for (std::size_t i = 0; i < v.size(); ++i) { if (v[i] % 2 == 0) { positions_to_modify.push_back(i); } } for (std::size_t idx : positions_to_modify) { v[idx] *= 10; }
// ✅ 安全方式 3:用算法返回的新迭代器 v = {1, 2, 3, 4, 5}; auto new_end = std::remove_if(v.begin(), v.end(), [](int x) { return x < 3; }); v.erase(new_end, v.end()); // 删除 < 3 的元素
return 0;}14.5 插入和删除操作
Section titled “14.5 插入和删除操作”push_back vs emplace_back
Section titled “push_back vs emplace_back”#include <vector>#include <iostream>#include <string>
struct Point { int x, y; Point(int x_, int y_) : x(x_), y(y_) { std::cout << "Point constructed: (" << x << ", " << y << ")\n"; } Point(const Point& p) : x(p.x), y(p.y) { std::cout << "Point copied\n"; }};
int main() { std::vector<Point> points;
std::cout << "=== push_back ===\n"; points.push_back(Point(1, 2)); // 临时对象被构造,然后拷贝/移动到 vector
std::cout << "\n=== emplace_back ===\n"; points.emplace_back(3, 4); // 直接在 vector 末尾构造
// emplace_back 更高效,避免临时对象的拷贝/移动
return 0;}insert 和 emplace
Section titled “insert 和 emplace”#include <vector>#include <iostream>#include <string>
int main() { std::vector<std::string> words = {"apple", "cherry"};
// insert - 插入元素(拷贝或移动) words.insert(words.begin() + 1, "banana"); // {"apple", "banana", "cherry"} words.insert(words.end(), "date"); // {"apple", "banana", "cherry", "date"}
// insert - 插入多个相同元素 words.insert(words.begin(), 2, "???"); // {"???", "???", "apple", "banana", "cherry", "date"}
// insert - 从另一个范围插入 std::vector<std::string> more = {"x", "y", "z"}; words.insert(words.end(), more.begin(), more.end()); // 添加更多
// emplace - 原位构造 words.emplace(words.begin() + 2, "embedded"); // 直接构造,不拷贝
// erase - 删除单个元素 words.erase(words.begin() + 1); // 删除第二个
// erase - 删除范围 words.erase(words.begin(), words.begin() + 2); // 删除前两个
// 打印 for (const auto& w : words) std::cout << w << " "; std::cout << std::endl;
return 0;}remove-erase 惯用法
Section titled “remove-erase 惯用法”#include <vector>#include <algorithm>#include <iostream>
int main() { std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// 删除所有偶数 auto new_end = std::remove_if(v.begin(), v.end(), [](int x) { return x % 2 == 0; }); v.erase(new_end, v.end()); // {1, 3, 5, 7, 9}
// 删除第一个满足条件的 v = {1, 2, 3, 2, 4, 2, 5}; auto it = std::find(v.begin(), v.end(), 2); if (it != v.end()) { v.erase(it); // 删除第一个 2 } // {1, 3, 2, 4, 2, 5}
// 删除所有特定值 v = {1, 2, 3, 2, 4, 2, 5}; v.erase(std::remove(v.begin(), v.end(), 2), v.end()); // {1, 3, 4, 5}
// 按条件删除(Lambda) v = {1, 2, 3, 4, 5, 6, 7, 8, 9}; v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x > 5; }), v.end()); // {1, 2, 3, 4, 5}
for (int x : v) std::cout << x << " "; std::cout << std::endl;
return 0;}14.6 内存管理详解
Section titled “14.6 内存管理详解”capacity 和 size
Section titled “capacity 和 size”#include <vector>#include <iostream>
int main() { std::vector<int> v;
std::cout << "Initial state:\n"; std::cout << " size: " << v.size() << "\n"; std::cout << " capacity: " << v.capacity() << "\n";
// 预留空间(避免多次重新分配) v.reserve(100); std::cout << "\nAfter reserve(100):\n"; std::cout << " size: " << v.size() << "\n"; std::cout << " capacity: " << v.capacity() << "\n";
// 添加元素 for (int i = 0; i < 50; ++i) { v.push_back(i); } std::cout << "\nAfter 50 push_backs:\n"; std::cout << " size: " << v.size() << "\n"; std::cout << " capacity: " << v.capacity() << "\n";
// 释放多余容量 v.shrink_to_fit(); std::cout << "\nAfter shrink_to_fit():\n"; std::cout << " size: " << v.size() << "\n"; std::cout << " capacity: " << v.capacity() << "\n";
// 请求最小容量 v.reserve(200); std::cout << "\nAfter reserve(200):\n"; std::cout << " capacity: " << v.capacity() << "\n";
return 0;}容量增长策略
Section titled “容量增长策略”#include <vector>#include <iostream>
int main() { // 典型的容量增长策略 std::vector<int> v;
std::cout << "Capacity growth:\n"; for (int i = 0; i < 20; ++i) { if (i == 0 || v.capacity() != v.size() - 1) { std::cout << "Size " << v.size() << " -> Capacity " << v.capacity() << "\n"; } v.push_back(i); }
// 注:容量增长是实现定义的,通常是 1.5x 或 2x // GCC: 2x, MSVC: 1.5x
return 0;}避免重新分配
Section titled “避免重新分配”#include <vector>#include <iostream>
int main() { // ❌ 低效:大量小规模 push_back std::vector<int> inefficient; for (int i = 0; i < 10000; ++i) { inefficient.push_back(i); // 可能多次重新分配 }
// ✅ 高效:先 reserve std::vector<int> efficient; efficient.reserve(10000); // 预分配 for (int i = 0; i < 10000; ++i) { efficient.push_back(i); // 不重新分配 }
// ✅ 也可以用 resize + 操作 std::vector<int> v(10000); // 直接分配 10000 个元素 for (int i = 0; i < 10000; ++i) { v[i] = i; // 使用下标操作 }
return 0;}内存分配异常
Section titled “内存分配异常”#include <vector>#include <iostream>#include <new>
int main() { // push_back 可能抛出 bad_alloc(内存不足) try { std::vector<int> v; v.reserve(std::numeric_limits<std::size_t>::max()); // 尝试分配过大内存 } catch (const std::bad_alloc& e) { std::cout << "Memory allocation failed: " << e.what() << "\n"; }
// emplace_back 也可能抛出 std::vector<std::vector<int>> vv; try { for (int i = 0; i < 1000000; ++i) { vv.emplace_back(1000000); // 每次分配大块内存 } } catch (const std::bad_alloc& e) { std::cout << "Out of memory!\n"; }
return 0;}14.7 二维 vector
Section titled “14.7 二维 vector”创建和初始化
Section titled “创建和初始化”#include <vector>#include <iostream>#include <iomanip>
int main() { // 3x4 的二维 vector,初始值为 0 std::vector<std::vector<int>> matrix(3, std::vector<int>(4, 0));
// 设置值 matrix[0][0] = 1; matrix[1][2] = 5;
// 打印 for (const auto& row : matrix) { for (int val : row) { std::cout << std::setw(3) << val << " "; } std::cout << "\n"; }
// 访问元素 int val = matrix[2][3]; // 第 3 行,第 4 列
return 0;}动态二维数组
Section titled “动态二维数组”#include <vector>#include <iostream>
// 创建任意大小的二维 vectorstd::vector<std::vector<double>> create_matrix(int rows, int cols, double init = 0.0) { return std::vector<std::vector<double>>( rows, std::vector<double>(cols, init));}
// 更好的方式:用一维 vector 模拟(更高效)std::vector<int> create_flat_matrix(int rows, int cols, int init = 0) { return std::vector<int>(rows * cols, init);}
// 访问扁平矩阵int get(const std::vector<int>& mat, int rows, int cols, int row, int col) { return mat[row * cols + col];}
void set(std::vector<int>& mat, int cols, int row, int col, int value) { mat[row * cols + col] = value;}
int main() { auto matrix = create_matrix(3, 4, 1.0);
// 扁平矩阵更高效(连续内存,缓存友好) auto flat = create_flat_matrix(3, 4, 0); set(flat, 4, 1, 2, 99); std::cout << get(flat, 4, 1, 2) << std::endl; // 99
return 0;}14.8 算法和转换
Section titled “14.8 算法和转换”#include <vector>#include <algorithm>#include <numeric>#include <iostream>#include <functional>
int main() { std::vector<int> v = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// 排序 std::sort(v.begin(), v.end()); // 升序 std::sort(v.begin(), v.end(), std::greater<int>()); // 降序 std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); // Lambda
// 查找 auto it = std::find(v.begin(), v.end(), 5); auto it2 = std::find_if(v.begin(), v.end(), [](int x) { return x > 5; });
// 二分查找(需要已排序) std::sort(v.begin(), v.end()); bool found = std::binary_search(v.begin(), v.end(), 5);
// 统计 int count = std::count(v.begin(), v.end(), 3); int evens = std::count_if(v.begin(), v.end(), [](int x) { return x % 2 == 0; });
// 求和 int sum = std::accumulate(v.begin(), v.end(), 0); double avg = static_cast<double>(sum) / v.size();
// 最大/最小 int max_val = *std::max_element(v.begin(), v.end()); int min_val = *std::min_element(v.begin(), v.end());
// 反序 std::reverse(v.begin(), v.end());
// 去重(需先排序) std::sort(v.begin(), v.end()); v.erase(std::unique(v.begin(), v.end()), v.end());
// 洗牌(随机) std::random_shuffle(v.begin(), v.end()); // C++14 已弃用 // C++20 用 std::ranges::shuffle
return 0;}transform
Section titled “transform”#include <vector>#include <algorithm>#include <string>#include <iostream>
int main() { std::vector<int> numbers = {1, 2, 3, 4, 5};
// 转换(平方) std::vector<int> squares; std::transform(numbers.begin(), numbers.end(), std::back_inserter(squares), [](int x) { return x * x; }); // squares = {1, 4, 9, 16, 25}
// 原地转换 std::transform(numbers.begin(), numbers.end(), numbers.begin(), [](int x) { return x * 2; }); // numbers = {2, 4, 6, 8, 10}
// 两个向量操作 std::vector<int> a = {1, 2, 3}; std::vector<int> b = {10, 20, 30}; std::vector<int> sums; std::transform(a.begin(), a.end(), b.begin(), std::back_inserter(sums), [](int x, int y) { return x + y; }); // sums = {11, 22, 33}
// 字符串转换 std::vector<std::string> words = {"hello", "world"}; std::vector<std::string> upper; std::transform(words.begin(), words.end(), std::back_inserter(upper), [](const std::string& s) { std::string result = s; std::transform(result.begin(), result.end(), result.begin(), ::toupper); return result; }); // upper = {"HELLO", "WORLD"}
return 0;}14.9 完整示例:成绩管理
Section titled “14.9 完整示例:成绩管理”#include <vector>#include <string>#include <iostream>#include <algorithm>#include <iomanip>#include <numeric>
struct Student { std::string name; std::vector<double> scores;
double average() const { if (scores.empty()) return 0.0; return std::accumulate(scores.begin(), scores.end(), 0.0) / scores.size(); }
double max_score() const { if (scores.empty()) return 0.0; return *std::max_element(scores.begin(), scores.end()); }
double min_score() const { if (scores.empty()) return 0.0; return *std::min_element(scores.begin(), scores.end()); }};
class GradeBook {private: std::vector<Student> students_;
public: void add_student(const std::string& name) { students_.push_back({name, {}}); }
void add_score(const std::string& name, double score) { auto it = std::find_if(students_.begin(), students_.end(), [&name](const Student& s) { return s.name == name; }); if (it != students_.end()) { it->scores.push_back(score); } }
void print_report() const { std::cout << std::string(60, '-') << "\n"; std::cout << std::left << std::setw(15) << "Name" << std::right << std::setw(10) << "Average" << std::setw(10) << "Max" << std::setw(10) << "Min" << "\n"; std::cout << std::string(60, '-') << "\n";
for (const auto& student : students_) { std::cout << std::left << std::setw(15) << student.name << std::right << std::fixed << std::setprecision(2) << std::setw(10) << student.average() << std::setw(10) << student.max_score() << std::setw(10) << student.min_score() << "\n"; }
// 班级平均 double class_avg = 0; int count = 0; for (const auto& s : students_) { class_avg += s.average() * s.scores.size(); count += s.scores.size(); } if (count > 0) { std::cout << std::string(60, '-') << "\n"; std::cout << "Class Average: " << std::fixed << std::setprecision(2) << (class_avg / count) << "\n"; } }
// 获取排名 std::vector<std::string> get_top_students(int n) const { std::vector<const Student*> sorted; for (const auto& s : students_) { sorted.push_back(&s); } std::sort(sorted.begin(), sorted.end(), [](const Student* a, const Student* b) { return a->average() > b->average(); });
std::vector<std::string> result; for (int i = 0; i < n && i < sorted.size(); ++i) { result.push_back(sorted[i]->name); } return result; }};
int main() { GradeBook book;
book.add_student("Alice"); book.add_student("Bob"); book.add_student("Charlie"); book.add_student("Diana");
// 添加成绩 book.add_score("Alice", 95); book.add_score("Alice", 88); book.add_score("Alice", 92);
book.add_score("Bob", 78); book.add_score("Bob", 85); book.add_score("Bob", 82);
book.add_score("Charlie", 91); book.add_score("Charlie", 94); book.add_score("Charlie", 89);
book.add_score("Diana", 83); book.add_score("Diana", 90); book.add_score("Diana", 88);
book.print_report();
std::cout << "\nTop 2 students:\n"; for (const auto& name : book.get_top_students(2)) { std::cout << "- " << name << "\n"; }
return 0;}14.10 章节总结
Section titled “14.10 章节总结”| 操作 | 说明 |
|---|---|
vector<T> v | 默认构造,空 vector |
vector<T> v(n) | n 个值初始化元素 |
vector<T> v(n, val) | n 个 val |
vector<T> v = {a, b, c} | 列表初始化 |
v.push_back(x) | 添加到末尾(拷贝/移动) |
v.emplace_back(args) | 原位构造(更高效) |
v.insert(it, x) | 在迭代器前插入 |
v.erase(it) | 删除迭代器处元素 |
v.reserve(n) | 预分配 n 个元素空间 |
v.shrink_to_fit() | 释放多余容量 |
v.size() | 元素个数 |
v.capacity() | 已分配空间 |
v[0] / v.at(0) | 访问元素 |
v.front() / v.back() | 首/尾元素 |
v.begin() / v.end() | 迭代器 |
性能提示:
- 大量插入前先
reserve() - 优先用
emplace而不是push - 修改后注意迭代器可能失效
下章预告:ch15 学习 std::unordered_map,哈希表的 C++ 实现。