vector容器
vector 容器是STL中最常用的容器之一,它和 array 容器非常类似,都可以看做是对C++普通数组的“升级版”。不同之处在于,array 实现的是静态数组(容量固定的数组),而 vector 实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,vector 会动态调整所占用的内存空间,整个过程无需人工干预,vector 常被称为向量容器。
vector 容器以类模板 vector<T>( T 表示存储元素的类型)的形式定义在 <vector> 头文件中,并位于 std 命名空间中。因此,在创建该容器之前,代码中需包含如下内容:
#include <vector> using namespace std;
注意,std 命名空间也可以在使用 vector 容器时额外注明,两种方式都可以。
创建vector容器的几种方式
#include <iostream> #include <vector> using namespace std; int main() { vector<int> vec1; vec1.push_back(1); vector<int> vec2(10); //10个元素 vector<int> vec3(10,5); //10个元素 每个元素的值都为5(可以是变量) vector<int> vec4(vec3); //通过存储元素类型相同的其它vector 创建新的vector system("pause"); return 0; }
vector容器的成员函数
函数成员 | 函数功能 |
---|---|
begin() | 返回指向容器中第一个元素的迭代器。 |
end() | 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用。 |
rbegin() | 返回指向最后一个元素的迭代器。 |
rend() | 返回指向第一个元素所在位置前一个位置的迭代器。 |
cbegin() | 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
cend() | 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
crbegin() | 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
crend() | 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。 |
size() | 返回实际元素个数。 |
max_size() | 返回元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。 |
resize() | 改变实际元素的个数。 |
capacity() | 返回当前容量。 |
empty() | 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。 |
reserve() | 增加容器的容量。 |
shrink _to_fit() | 将内存减少到等于当前元素实际所使用的大小。 |
operator[ ] | 重载了 [ ] 运算符,可以向访问数组中元素那样,通过下标即可访问甚至修改 vector 容器中的元素。 |
at() | 使用经过边界检查的索引访问元素。 |
front() | 返回第一个元素的引用。 |
back() | 返回最后一个元素的引用。 |
data() | 返回指向容器中第一个元素的指针。 |
assign() | 用新元素替换原有内容。 |
push_back() | 在序列的尾部添加一个元素。 |
pop_back() | 移出序列尾部的元素。 |
insert() | 在指定的位置插入一个或多个元素。 |
erase() | 移出一个元素或一段元素。 |
clear() | 移出所有的元素,容器大小变为 0。 |
swap() | 交换两个容器的所有元素。 |
emplace() | 在指定的位置直接生成一个元素。 |
emplace_back() | 在序列尾部生成一个元素。 |
#include <iostream> #include <vector> using namespace std; int main() { vector<char> vec; vec.push_back('S'); vec.push_back('T'); vec.push_back('L'); cout << vec.size() << endl; //输出元素个数 //迭代器遍历 vector<char>::iterator ite = vec.begin(); while(ite != vec.end()) { cout << *ite << endl; ite++; } vec.insert(vec.begin(),'C'); //在开头插入'C' cout << vec.at(0) << endl; system("pause"); return 0; }
如何避免vector容器不必要的扩容
vector内存成长方式可归结以下三步:
-
另觅更大空间;
-
将原数据复制过去;
-
释放原空间。
#include <iostream> #include <vector> using namespace std; int main() { vector<int> vec; for(int i=0;i<10;i++) { vec.push_back(i); cout << "size:" << vec.size() << " capacity:" << vec.capacity() << endl; } system("pause"); return 0; }
输出内容:
size:1 capacity:1 size:2 capacity:2 size:3 capacity:3 size:4 capacity:4 size:5 capacity:6 size:6 capacity:6 size:7 capacity:9 size:8 capacity:9 size:9 capacity:9 size:10 capacity:13
vector中size()和capacity()的区别
-
size() (大小)指容器当前拥有元素的个数;
-
capacity() (容量)指容器在必须分配存储空间之前可以存储元素的总数;
不同的编译器实现的扩容方式不一样,一般是1.5倍和2倍。
vector的容量之所以重要,有以下两个原因:
-
容器的大小一旦超过capacity的大小,vector会重新配置内部的存储器,导致和vector元素相关的引用、指针、迭代器都会失效。
-
内存的重新配置会很耗时间。
迭代器失效例子如下:
#include <iostream> #include <vector> using namespace std; int main() { vector<int> vec(10,1); vector<int>::iterator ite = vec.begin(); for(int i=0;i<10;i++) { cout << *ite << endl; vec.push_back(i); cout << "size:" << vec.size() << " capacity:" << vec.capacity() << endl; ite++; } system("pause"); return 0; }
避免内存重新配置的方法
-
reserve()保留适当容量
-
利用构造函数创建出足够空间
#include <iostream> #include <vector> using namespace std; int main() { vector<int> vec(10,1); vec.reserve(20); vector<int>::iterator ite = vec.begin(); for(int i=0;i<10;i++) { cout << *ite << endl; vec.push_back(i); cout << "size:" << vec.size() << " capacity:" << vec.capacity() << endl; ite++; } system("pause"); return 0; }