vector简介
vector是序列式容器(sequence containers)中的一种。
向量(vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。
vector的数据安排以及操作方式,与array非常相似。两者唯一的差别在于空间的运用的灵活性。array是静态空间,一旦配置了就不能改变。vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。因此,vector的运用对于内存的合理利用与运用的灵活性有很大的帮助,我们再也不必因为害怕空间不足而一开始就要求一个大块头array了,我们可以安心使用vector,吃多少用多少。
vector的数据结构
vector所采用的数据结构非常简单:线性连续空间。它以两个迭代器start和finish分别指向配置得来的连续空间中目前已经被使用的范围(符合STL规范之"前闭后开"区间),并以迭代器end_of_storage指向整块连续空间(含备用空间)的尾端。
另外在vector当中具有容量(capacity)的概念,这是为了降低空间配置时的速度成本,vector实际配置的大小可能比客户端需求量更大一些,以备将来可能的扩充。换而言之,一个vector的容量永远大于或等于其大小。一旦容量等于大小,便是满载,下次再有新增元素,整个vector就得另觅居所。
在vector当中包含三个迭代器成员变量,分别是:
iterator start // 表示目前使用空间的头
iterator finish // 表示目前使用空间的尾
iterator end_of_storage // 表示目前可用空间的尾
下面通过一个测试程序来观察一下vector的特性:
#include
#include
#include
using namespace std;
int main()
{
vector iv(2, 9);
cout << "size=" << iv.size() << endl; // size=2
cout << "capacity=" << iv.capacity() << endl; // capacity=2
iv.push_back(1);
cout << "size=" << iv.size() << endl; // size=3
cout << "capacity=" << iv.capacity() << endl; // capacity=3
iv.push_back(2);
cout << "size=" << iv.size() << endl; // size=4
cout << "capacity=" << iv.capacity() << endl; // capacity=4
iv.push_back(3);
cout << "size=" << iv.size() << endl; // size=5
cout << "capacity=" << iv.capacity() << endl; // capacity=6
iv.push_back(4);
cout << "size=" << iv.size() << endl; // size=6
cout << "capacity=" << iv.capacity() << endl; // capacity=6
for (auto i : iv)
cout << i << " "; // 9 9 1 2 3 4
cout << endl;
iv.push_back(5);
cout << "size=" << iv.size() << endl; // size=7
cout << "capacity=" << iv.capacity() << endl; // capacity=9
for (auto i : iv)
cout << i << " "; // 9 9 1 2 3 4 5
cout << endl;
iv.pop_back();
iv.pop_back();
cout << "size=" << iv.size() << endl; // size=5
cout << "capacity=" << iv.capacity() << endl; // capacity=9
iv.pop_back();
cout << "size=" << iv.size() << endl; // size=4
cout << "capacity=" << iv.capacity() << endl; // capacity=9
vector::iterator ivite = find(iv.begin(), iv.end(), 1);
if (ivite != iv.end())
iv.erase(ivite);
cout << "size=" << iv.size() << endl; // size=3
cout << "capacity=" << iv.capacity() << endl; // capacity=9
for (auto i : iv)
cout << i << " "; // 9 9 2
cout << endl;
ivite = find(iv.begin(), iv.end(), 2);
if (ivite != iv.end())
iv.insert(ivite, 3, 7);
cout << "size=" << iv.size() << endl; // size=6
cout << "capacity=" << iv.capacity() << endl; // capacity=9
for (auto i : iv)
cout << i << " "; // 9 9 7 7 7 2
cout << endl;
iv.clear();
cout << "size=" << iv.size() << endl; // size=0
cout << "capacity=" << iv.capacity() << endl; // capacity=9
return 0;
}
通过测试结构我们能够看到,vector会在满载后的下一次插入操作时进行动态扩容,在我的编译器下扩容的倍数为1.5倍,不同编译器具体不同,在STL源码剖析一书当中的扩容倍数为2。
这里需要注意的是,所谓动态增加大小,并不是在原空间之后接续新空间(因为无法保证原空间之后尚可有可供配置的空间),而是以原大小的两倍配置一块较大空间,然后将原内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。
因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。这是程序员易犯的一个错误,务需小心。
注意事项:在使用迭代器遍历操作vector时,切记不要在循环内部进行任何改变vector大小的操作,一旦引起数据空间重新配置或数据移动,则会造成迭代器失效的状况,进而引发无法预知的错误。
vector的常用操作
构造函数:
#include
#include
#include
using namespace std;
int main()
{
vector ivec1; // 创建一个空vector
cout << "size=" << ivec1.size() << endl; // size=0
cout << "capacity=" << ivec1.capacity() << endl; // capacity=0
vector ivec2(5); // 创建一个vector,元素个数为nSize(这里需要注意的是,所有的元素会被默认初始化)
cout << "size=" << ivec2.size() << endl; // size=5
cout << "capacity=" << ivec2.capacity() << endl; // capacity=5
for (auto i : ivec2)
cout << i << " "; // 0 0 0 0 0
cout << endl;
vector ivec3(6, 6); // 创建一个vector,元素个数为nSize,且值均为t(所有元素默认值为t)
cout << "size=" << ivec3.size() << endl; // size=6
cout << "capacity=" << ivec3.capacity() << endl; // capacity=6
for (auto i : ivec3)
cout << i << " "; // 6 6 6 6 6 6
cout << endl;
vector ivec4(ivec3); // 复制构造函数
cout << "size=" << ivec4.size() << endl; // size=6
cout << "capacity=" << ivec4.capacity() << endl; // capacity=6
for (auto i : ivec4)
cout << i << " "; // 6 6 6 6 6 6
cout << endl;
const int length = 5;
int a[length] = { 5, 4, 3, 2, 1 };
vector ivec5(a, a + length); // 复制[begin, end)区间内另一个数组的元素到vector中
cout << "size=" << ivec5.size() << endl; // size=5
cout << "capacity=" << ivec5.capacity() << endl; // capacity=5
for (auto i : ivec5)
cout << i << " "; // 5 4 3 2 1
cout << endl;
}
插入函数:
#include
#include
#include
using namespace std;
int main()
{
vector ivec = { 0, 1, 2, 3, 4, 5 };
ivec.push_back(6); // 向量尾部增加一个元素X
vector::iterator ivecite = find(ivec.begin(), ivec.end(), 3);
if (ivecite != ivec.end())
ivec.insert(ivecite, 99); // 向量中迭代器指向元素前增加一个元素x(前插法)
for (auto i : ivec)
cout << i << " "; // 0 1 2 99 3 4 5
cout << endl;
ivecite = find(ivec.begin(), ivec.end(), 99);
if (ivecite != ivec.end())
ivec.insert(ivecite, 3, 9); // 向量中迭代器指向元素前增加n个相同的元素x
for (auto i : ivec)
cout << i << " "; // 0 1 2 9 9 9 99 3 4 5
cout << endl;
const int length = 3;
int a[length] = { 3, 2, 1 };
ivec.insert(ivec.begin(), a, a + length); // 向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据
for (auto i : ivec)
cout << i << " "; // 3 2 1 0 1 2 9 9 9 99 3 4 5
cout << endl;
}
删除函数:
#include
#include
#include
using namespace std;
int main()
{
vector ivec = { 0, 1, 2, 3, 4, 5 };
auto ivecite = find(ivec.begin(), ivec.end(), 4);
if (ivecite != ivec.end()) // 删除向量中迭代器指向元素,并返回指向下一个元素的迭代器
cout << *(ivec.erase(ivecite)) << endl; // 5
cout << "size=" << ivec.size() << endl; // size=5
cout << "capacity=" << ivec.capacity() << endl; // capacity=6
for (auto i : ivec)
cout << i << " "; // 0 1 2 3 5
cout << endl;
ivecite = find(ivec.begin(), ivec.end(), 3);
if (ivecite != ivec.end())
ivec.erase(ivecite, ivec.end()); // 删除向量中[first,last)中元素
cout << "size=" << ivec.size() << endl; // size=3
cout << "capacity=" << ivec.capacity() << endl; // capacity=6
for (auto i : ivec)
cout << i << " "; // 0 1 2
cout << endl;
if (!ivec.empty())
ivec.pop_back(); // 删除向量中最后一个元素
cout << "size=" << ivec.size() << endl; // size=2
cout << "capacity=" << ivec.capacity() << endl; // capacity=6
for (auto i : ivec)
cout << i << " "; // 0 1
cout << endl;
ivec.clear(); // 清空向量中所有元素
cout << "size=" << ivec.size() << endl; // size=0
cout << "capacity=" << ivec.capacity() << endl; // capacity=6
ivec.pop_back();
}
遍历函数:
#include
#include
#include
using namespace std;
int main()
{
vector ivec = { 0, 1, 2, 3, 4, 5 };
cout << ivec.at(2) << endl; // 2 返回pos位置元素的引用
cout << ivec[2] << endl; // 2
cout << ivec.front() << endl; // 0 返回首元素的引用
cout << ivec.back() << endl; // 5 返回尾元素的引用
auto first = ivec.begin(); // 返回向量头指针,指向第一个元素
auto last = ivec.end(); // 返回向量尾指针,指向向量最后一个元素的下一个位置
for (; first != last; ++first)
cout << *first << " "; // 0 1 2 3 4 5
cout << endl;
auto r_first = ivec.rbegin(); // 反向迭代器,指向最后一个元素
auto r_last = ivec.rend(); // 反向迭代器,指向第一个元素之前的位置
for (; r_first != r_last; ++r_first)
cout << *r_first << " "; // 5 4 3 2 1 0
cout << endl;
vector ivec2(ivec.rbegin(), ivec.rend());
for (auto i : ivec2)
cout << i << " "; // 5 4 3 2 1 0
cout << endl;
}
判断函数:
#include
#include
#include
using namespace std;
int main()
{
vector ivec;
if (ivec.empty()) // 判断向量是否为空,若为空,则向量中无元素
cout << "ivec is empty!" << endl;
}