概述
本文是对vector容器的基本操作初探。
STL组件的相互关系请阅读【STL】STL六大组件概述。Array基础操作请阅读【STL】浅析Array
Vector是封装了动态大小数组的顺序容器。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,vector是一个能够存放任意类型的动态数组。
本文首先介绍了vector容器特点,然后在Code示例以注释方式介绍vector初始化、vector.size()、vector.front()、vector.back()、vector.data()等操作。具体操作演示请阅本文Code示例。
std::vector特点
1、std::vector就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。
2、std::vector本质讲,vector使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector并不会每次都重新分配大小。
3、std::vector分配空间策略,vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。
vector添加元素时,分配的a byte的空间,不够用情况下,将会另外开辟一个2a byte的空间,继续添加元素。
4、std::vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。
5、std::vector与其它动态序列容器相比(deque, list and forward_list), vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。
上述特点参考了博客【C++】STL——vector的简单介绍
Code示例
以Code示例进行介绍vector最基础的操作。
#include <vector>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio>
#include <iostream>
#include <ctime>
#include <algorithm>
using namespace std;
long VALUE = 1000000;
namespace jj02 {
void test_vector(long& value)
{
cout << "\ntest_vector().................\n";
//初始化vector <>代表模板初始化为string
vector<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i) {
//异常处理 防止value太大,导致无法分配内存空间
try {
snprintf(buf, 10, "%d", rand());
//.push_back() 从vector容器数据后端添加元素
//例如vector 为 [* * * * * * *].push_back(%) = [* * * * * * * %]
//vector 增长原理 [vector 当分配的a字节的空间,不够用时。
// 将会另外开辟一个2a字节的空间,继续添加元素]
c.push_back(string(buf));
}
catch (exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (double)(clock() - timeStart) / CLOCKS_PER_SEC * 1000 << "ms" << endl;
cout << "vector.max_size()=" << c.max_size() << endl; //返回容器能够容纳的最大元素数量,注意,这个数量实际上取决于操作系统和编译器的限制
cout << "vector.size()= " << c.size() << endl; //vector的元素数量
cout << "vector.front()= " << c.front() << endl; //vector的第一个元素
cout << "vector.back()= " << c.back() << endl; //vector的最后一个元素
cout << "vector.data()= " << c.data() << endl; //vector的第一个元素的地址
cout << "vector.capacity()= " << c.capacity() << endl << endl; //vector当前能够容纳的元素数量。注意,capacity()函数返回的是容器分配内存能够容纳的元素数量的数量,而不是元素的实际数量。
string target = get_a_target_string();
{
timeStart = clock();
//STL容器采用左闭右开 [ ) 的形式存储
//vector.begin()返回首元素迭代器 .end()返回末尾元素再后以为的迭代器
//find() 函数用于查找容器中第一个等于指定值的元素,并返回指向该元素的迭代器。
//如果在容器中找不到指定值,则返回指向容器末尾[.end()]的迭代器。
auto pItem = find(c.begin(), c.end(), target);
cout << "std::find(), milli-seconds : " << (double)(clock() - timeStart) * 1000 / CLOCKS_PER_SEC << "ms" << endl;
if (pItem != c.end())
cout << "fount, " << *pItem << endl << endl;
else
cout << "not fount!" << endl << endl;
}
{
timeStart = clock();
/*sort(begin, end, cmp),其中begin为指向待sort()的数组的第一个元素的指针,
end为指向待sort()的数组的最后一个元素的下一个位置的指针,cmp参数为排序准则,cmp参数可以不写,
如果不写的话,默认从小到大进行排序。
sort()并非只是普通的快速排序,除了对普通的快速排序进行优化,它还结合了插入排序和堆排序。
根据不同的数量级别以及不同情况,能自动选用合适的排序方法。
*/
sort(c.begin(), c.end());
cout << "sort(), milli-seconds : " << (double)(clock() - timeStart) * 1000 / CLOCKS_PER_SEC << "ms" << endl;
timeStart = clock();
/*bsearch
使用二分查找,查找一个被排序过的数组s
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
key: 指向要查找的元素
base : 指向被查找的数组
nmemb : 被查找数组的大小
size : 被查找数组元素的大小
int (*compar)(const void*, const void*) : 比对的函数*/
string* pItem = (string*)::bsearch(&target, (c.data()), c.size(), sizeof(string), compareStrings);
cout << "bsearch(), milli-seconds : " << (double)(clock() - timeStart) * 1000 / CLOCKS_PER_SEC << "ms" << endl;
if (pItem != NULL)
cout << "found, " << *pItem << endl << endl;
else
cout << "not found! " << endl << endl;
}
}
}
int main()
{
jj02::test_vector(VALUE);
return 0;
}
运行结果:
参考文献:
STL源码剖析