vector容器

vector是一个长度可变的数组,支持动态扩容,因此其中的元素都存储在堆上。
vector是一个模板类,第一个模板参数是数组元素的类型。如:声明一个数组arr。其元素数据类型为int:

1
2
3
4
5
6
7
#include <vector>
using namespace std;
int main()
{
vector<int> arr;
return 0;
}

构造函数 和 size()

vector可以在构造时指定初始长度,通过size()获取数组的长度。
这个显式构造函数,默认会将所有元素都初始化为对应数据类型的初始值,无需手动memset()

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <vector>
#include <iostream>
using namespace std;
int main()
{
/*
构造函数:explicit vector(size_t n);
元素个数:size_t size() const noexcept;
*/
vector<int> arr(4);
cout << arr.size() << endl;
return 0;
}

该显式构造函数还可以指定第二个参数,这样就可以用指定值去初始化整个数组。
比如vector<int> arr(4, 22);等价于vector<int> arr = {22, 22, 22, 22};

初始化列表

c++11新特性支持:在构造时直接使用初始化列表,去初始化元素的值。相比先创建再赋值更加直观。

1
2
3
4
5
6
7
8
9
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector<int> arr{1, 2, 3, 4, 5, 6}; // 等价于 vector<int> arr = {1, 2, 3, 4, 5, 6};
cout << arr.size() << endl;
return 0;
}

访问和修改元素

[ ]

[ ]可以访问指定索引的元素,出于效率考虑,[ ]不会检查是否越界;

at()

为防止索引越界,可用arr.at(n)替代arr[n]
at()会检测索引n是否越界,若越界,则会抛出异常std::out_of_range,使得程序提前终止,此时可以使用try-catch捕获异常,从而快速定位错误。
at()相比[]来说,更加安全和便于调试,但会损失一定的性能。

1
2
int &at(size_t i);
int const &at(size_t i) const;

[ ] 和 at()

[ ]at()不仅可以读取元素,也可以写入元素。因为其返回的是元素的引用int&

resize()

除了在构造中指定数组长度,也可以构造之后再用resize()设置数组长度。

1
2
vector<int> arr;
arr.resize(4);

resize()也有第二个参数的一个重载函数,使用第二个参数填充所有新元素的值(原有的元素值保持不变)。

1
2
vector<int> arr;
arr.resize(4, 99);

clear()

清空数组:长度变为0;
arr.clear(); 等价于 arr.resize(0);arr = {};;

通常clear()resize()会组合使用,先clear()resize()

push_back()

可以在数组末尾追加一个元素;

1
2
vector<int> arr = {1, 2, 3, 4};
arr.push_back(5);

pop_back()

删除数组末尾的元素,只是减少了一个元素,并不会将末尾的元素返回。

1
2
vector<int> arr = {1, 2, 3, 4, 5};
arr.pop_back(); // 等价于:arr.resize(arr.size() - 1);

back()

back()可以获取末尾元素的值,正好与pop_back()相辅相成。

1
2
vector<int> arr = {1, 2, 3};
arr.back(); // 等价于:arr.at(arr.size() - 1);

front()

获取首个元素值;等价于arr.at(0);

data()

返回指向数组的首地址指针,等价于&arr[0]
通常配合size()使用:连续的动态数组只需要首地址和数组长度即可完全确定。

int main()
{
    vector<int> arr = {1, 2, 3};
    int *p = arr.data();
    memset(p, 88, sizeof(int) * arr.size());
    return 0;
}