C++ STL应用与实现2: 如何使用std::vector
Posted elloop
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ STL应用与实现2: 如何使用std::vector相关的知识,希望对你有一定的参考价值。
本系列文章的目录在这里:目录. 通过目录里可以对STL总体有个大概了解
前言
本文介绍vector容器。vector是STL容器中最为常用的一个,它是序列式容器的代表,是对动态数组的抽象封装。
vector 是什么
vector是一个class template,要用它需包含#include <vector>
基本用法及常识
创建 & 增删改查
// 使用初始化列表(initializer list) since C++11
// 更多创建方式见参考链接
vector<int> vi 1, 2, 3;
// 增
for (int i=4; i<10; ++i)
vi.push_back(i);
// 打印内容
printContainer(vi, "init, vi: ");
// 查 & 改, random access and modify
vi[0] = 10;
// 删
// 删第一个元素
auto iter = vi.begin();
vi.erase(iter);
printContainer(vi, "erase begin, vi: ");
// use <algorithm> std::find to locate pos of 5 in vi.
// 删值为5的元素
iter = find(vi.begin(), vi.end(), 5);
if (iter != vi.end())
pln("erase 5");
vi.erase(iter);
printContainer(vi, "erase 5, vi: ");
输出:
init vi: 10 2 3 4 5 6 7 8 9
erase begin, vi: 2 3 4 5 6 7 8 9
erase 5
erase 5, vi: 2 3 4 6 7 8 9
以下是辅助函数printContainer的实现。
#define cr do std::cout << std::endl; while (0);
template <typename T>
inline void p(const T & x)
std::cout << x;
template <typename Con>
void printContainer(const Con & c, const std::string& opt = "")
if (!opt.empty())
p(opt);
auto iter = c.begin();
while (iter != c.end())
p(*iter);
p(" ");
++iter;
cr;
vector需要注意的点
0. copy in copy out是所有的STL容器的工作原理(参见Effective STL)
因此,使用vector等容器的一个原则是,为了避免拷贝开销,不要直接把大的对象直接往里塞,而是使用指针。
1. 由于其顺序存储的特性,vector插入删除操作的时间复杂度是O(n)
2. vector的容量capacity
预先指定capacity是个好习惯
vector的capacity:即指vector最大能容纳多少元素
vector的size:即当前存入了多少元素
所以始终有size <= capacity,正如我们自己实现动态数组所考虑的一样,当size == capacity的时候,再要增加元素就要扩容,重新找一块更大的内存把元素转移过去,这种扩容操作有两个后果:
使得vector原来的引用、指针、迭代器失效
内存分配消耗了时间
因此,要尽可能的让这种扩容操作少发生,通常的做法是往vector中添加元素之前,预先指定一个capacity,比如:
vector<int> vi; // capacity: 0
vector<int> vi(100); // capacity: 100
// or
vi.reserve(100);
两种方式指定容量:1. 构造函数里;2. reserve() 函数
有些版本的vector实现里,如果用户不预先指定一个capacity,那么在第一次往容器里添加元素的时候,vector会自动分配一个指定大小(如2K)的内存块以避免频繁发生扩容。这可能导致的问题是,如果你有很多个这样的vector,每个都保存很少的数据,那么这些预先分配的内存块将是一笔很大的浪费。这又体现了自己预先指定一个capacity的必要性。
如何缩小容量
c++11之前,需要借助swap,像下面这个函数模板:shrinkCapacity那样。
c++11之后,调用shrink_to_fit()
即可。
template <typename T>
void shrinkCapacity(vector<T> &v)
vector<T> temp(v);
temp.swap(v);
RUN_GTEST(VectorTest, Shrink, @@);
vector<int> vi;
vi.reserve(30);
vi.push_back(1);
psln(vi.capacity()); // 30
shrinkCapacity(vi); // before c++11
// vi.shrink_to_fit(); // since c++ 11
psln(vi.capacity()); // 1
END_TEST;
3. vector的成员函数都不做边界检查(at方法会抛异常),使用者要自己确保迭代器和索引值的合法性。
源码及参考链接
作者水平有限,对相关知识的理解和总结难免有错误,还望给予指正,非常感谢!
在这里也能看到这篇文章:github博客, CSDN博客, 欢迎访问
以上是关于C++ STL应用与实现2: 如何使用std::vector的主要内容,如果未能解决你的问题,请参考以下文章
C++ STL应用与实现2: 如何使用std::vector
C++ STL应用与实现86: 如何使用std::accumulate