C++STL 系列(二):vector 容器详解与示例
仓库链接
本仓库提供STL相关每一篇文章的完整可运行示例代码。
git clone https://github.com/MaikieMaiky/cpp_STL.git
vector基本概念
- vector数据结构和数组非常相似,也成为单端数组(只在尾端可以进行push/pop)
vector与普通数组的区别:
- 普通数组是静态数组,大小固定不可变
- vector是动态数组,大小可以动态扩展
动态扩展
- 扩展时寻找一块更大的内存空间,拷贝原数据到新空间,释放原空间
front() back()
----------------------------------
| -----> push_back()
| 1 2 _ 3 4 5
^ | ^ ^ ^ ^ pop_back()
| --|----------|-------------|------|---
v.rend() v.begin() insert() v.rbegin() v.end()
- 常用iterator为v.begin()和v.end
- vector 的 iterator 支持随机访问
vector构造函数
原型:
-
vector();// 无参构造函数 -
vector(int n, const T& value);// 拷贝n个value到vector中 -
vector(const vector& v);// 拷贝构造函数 -
vector(InputIterator first, InputIterator last);// 复制[first,last)范围的元素到vector中,一般写作vector(v.begin(), v.end()) -
示例
// vector的构造函数 /** * vector(); // 无参构造函数 * vector(int n, const T& value); // 拷贝n个value到vector中 * vector(const vector& v); // 拷贝构造函数 * vector(InputIterator first, InputIterator last); // 复制[first, * last)范围的元素到vector中,一般写作vector(v.begin(), v.end()) */ #include <iostream> #include <vector> using namespace std; void print_vector(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { // 1. 无参构造 vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } print_vector(v1); // 2. 拷贝n个value到vector中 vector<int> v2(10, 1); print_vector(v2); // 3. 拷贝构造函数 vector<int> v3(v1); print_vector(v3); // 4. 复制[first, last)范围的元素到vector中 vector<int> v4(v1.begin(), v1.end()); print_vector(v4); } int main() { test0(); return 0; }
vector赋值操作
原型:
-
vector& operator=(const vector& v);// 重载=操作符 -
assign(int n, const T& value);// 复制n个value到vector中 -
assign(InputIterator first, InputIterator last);// 复制[first, last)范围的元素到vector中,一般写作assign(v.begin(), v.end()) -
示例
// vector的赋值操作 /** * vector& operator=(const vector& v); // 重载=操作符 * assign(int n, const T& value); // 复制n个value到vector中 * assign(InputIterator first, InputIterator last); // 复制[first, last)范围的元素到vector中,一般写作assign(v.begin(), v.end()) */ #include <iostream> #include <vector> using namespace std; void print_vector(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { // 无参构造 vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } print_vector(v1); // 重载=操作符 vector<int> v2; v2 = v1; print_vector(v2); // 复制n个value到vector中 vector<int> v3; v3.assign(10, 100); print_vector(v3); // 复制[first, last)范围的元素到vector中 vector<int> v4; v4.assign(v1.begin(), v1.end()); print_vector(v4); } int main() { test0(); return 0; }
vector容量和大小
原型:
-
empty();// 判断vector是否为空 -
capacity();// 返回vector的容量 -
size();// 返回vector中元素的个数 -
resize(int size);// 重新指定vector的容量,若容器变长,则以默认值填充新位置。
// 若容器变短,则超出容器长度的元素被删除。 -
resize(int size, const T& value);// 重新指定vector的容量,若容器变长,则以value填充新位置。
// 若容器变短,则超出容器长度的元素被删除。 -
示例
// vector的容量与大小 /** * empty(); // 判断vector是否为空 * capacity(); // 返回vector的容量 * size(); // 返回vector中元素的个数 * resize(int size); // 重新指定vector的容量,若容器变长,则以默认值填充新位置。 * // 若容器变短,则超出容器长度的元素被删除。 * resize(int size, const T& value); // 重新指定vector的容量,若容器变长,则以value填充新位置。 * // 若容器变短,则超出容器长度的元素被删除。 */ #include <iostream> #include <vector> using namespace std; void print_vector(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { vector<int> v1; // 1. 判断是否为空 if (v1.empty()) { cout << "v1 is empty" << endl; } else { cout << "v1 is not empty" << endl; } // 2. 添加元素 for (int i = 0; i < 5; i++) { v1.push_back(i); } // 3. 查看容量和大小 cout << "v1 capacity: " << v1.capacity() << endl; cout << "v1 size: " << v1.size() << endl; print_vector(v1); // 4. 重新指定大小, 以默认值填充新位置 v1.resize(15); print_vector(v1); // 5. 重新指定大小, 以value填充新位置 v1.resize(20, 100); print_vector(v1); // 6. 重新指定大小,超出容器长度的元素被删除 v1.resize(3); print_vector(v1); } int main() { test0(); return 0; }
vector插入和删除
原型:
-
push_back(const T& value);// 在末尾添加元素 -
pop_back();// 删除末尾的元素 -
insert(iterator pos, const T& value);// 在pos位置插入value -
insert(iterator pos, int n, const T& value);// 在pos位置插入n个value -
erase(iterator pos);// 删除pos位置的元素 -
erase(iterator first, iterator last);// 删除[first, last)范围的元素 -
clear();// 清空vector -
示例
// vector的插入和删除 /** * push_back(const T& value); // 在末尾添加元素 * pop_back(); // 删除末尾的元素 * insert(iterator pos, const T& value); // 在pos位置插入value * insert(iterator pos, int n, const T& value); // 在pos位置插入n个value * erase(iterator pos); // 删除pos位置的元素 * erase(iterator first, iterator last); // 删除[first, last)范围的元素 * clear(); // 清空vector */ #include <iostream> #include <vector> using namespace std; void print_vector(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { vector<int> v; for (int i = 0; i < 10; i++) { v.push_back(i); } print_vector(v); // 1. 在末尾添加元素 v.push_back(100); print_vector(v); // 2. 删除末尾的元素 for (int i = 0; i < 5; i++) { v.pop_back(); } print_vector(v); // 3. 在pos位置插入value v.insert(v.begin(), 100); print_vector(v); // 4. 在pos位置插入n个value v.insert(v.begin(), 2, 88); print_vector(v); // 5. 删除pos位置的元素 v.erase(v.begin() + 2); print_vector(v); // 6. 删除[first, last)范围的元素 v.erase(v.begin() + 1, v.begin() + 3); print_vector(v); // 7. 清空vector v.clear(); print_vector(v); } int main() { test0(); return 0; }
注意:insert和erase要传入迭代器,入门时我们可以直接把迭代器当作指针来使用,比如可以直接通过*iterator来取出容器中的元素
vector数据存取
原型:
-
at(int idx);// 通过at方法访问元素 -
operator[];// 通过[ ]访问元素,类似C风格数组访问方式 -
front();// 访问第一个元素 -
back();// 访问最后一个元素 -
示例
// vector的数据存取 /** * at(int idx); // 通过索引访问元素 * operator[]; // 通过索引访问元素 * front(); // 访问第一个元素 * back(); // 访问最后一个元素 */ #include <iostream> #include <vector> using namespace std; void test0() { vector<int> v; for (int i = 0; i < 10; i++) { v.push_back(i); } // 1. 通过索引访问元素 cout << "v[0] = " << v[0] << endl; cout << "v.at(2) = " << v.at(2) << endl; // 2. 访问第一个元素 cout << "the first element is " << v.front() << endl; // 3. 访问最后一个元素 cout << "the last element is " << v.back() << endl; } int main() { test0(); return 0; }
除了使用迭代器获取元素,还可以使用at, [ ]来获取
vector容器互换
原型:
-
swap(vector& vec);// 将vec与当前vector进行交换 -
实际用法 - 内存收缩:
vector<int>(vec).swap(vec)
创建了一个vector → 使用后vector的capacity较大,而size很小 → 通过创建一个匿名对象(临时对象)通过拷贝构造复制当前的size,并设置当前size为capacity → 使用swap交换 → 原vec指向匿名对象的内容 → 匿名对象负责原vec内容的析构 -
示例
// vector容器互换 /** * swap(vector& vec); // 将vec与当前vector进行交换 */ #include <iostream> #include <vector> using namespace std; void print_vector(vector<int> v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } void test0() { vector<int> v1; for (int i = 0; i < 10; i++) { v1.push_back(i); } cout << "v1 = "; print_vector(v1); vector<int> v2; for (int i = 10; i > 0; i--) { v2.push_back(i); } cout << "v2 = "; print_vector(v2); // 互换 v1.swap(v2); cout << "v1 = "; print_vector(v1); cout << "v2 = "; print_vector(v2); } // 实际应用 void test1() { vector<int> v; for (int i = 0; i < 100000; i++) { v.push_back(i); } cout << "v capacity: " << v.capacity() << endl; cout << "v size: " << v.size() << endl; // size缩小为3 capacity不变 v.resize(3); cout << "after resize" << endl; cout << "v capacity: " << v.capacity() << endl; cout << "v size: " << v.size() << endl; // 内存收缩 vector<int>(不写名字)(v) 匿名对象 拷贝构造函数复制原对象的size 并以此为capacity 然后与原对象交换指向 匿名函数负责释放原对象内存 vector<int>(v).swap(v); cout << "after swap" << endl; cout << "v capacity: " << v.capacity() << endl; cout << "v size: " << v.size() << endl; } int main() { // test0(); test1(); return 0; }
vector预留空间
提前一次分配大块内存给capacity,减少vector动态扩容的次数,提高效率
特点
- 预留位置不初始化
- 预留位置的元素不可访问
原型
-
reserve(int len);// 预留len个元素的容量 -
示例
// vector预留空间 /** * reserve(int len); // 预留len个元素的容量 */ #include <iostream> #include <vector> using namespace std; // 通过提前预留大块空间 减少vector扩容次数 提高效率 void test0() { vector<int> v; // 开关注释 对比是否预留空间对扩容次数的影响 // v.reserve(100000); // 记录每次扩容的地址 如果地址发生变化 则说明发生了扩容 int* p = NULL; int count = 0; for (int i = 0; i < 100000; i++) { v.push_back(i); if (p != &v[0]) { p = &v[0]; count++; } } cout << "the number of times of expansion: " << count << endl; } int main() { test0(); return 0; }
更多推荐

所有评论(0)