C++ 学习笔记
C++ vector 容器浅析
数组
简介
数组其实是一个指针
1
2int example[5]; // in stack
int* ptr = example;数组取值的两种方式
1
2
3
4
5*(example+2) = 5;
example[1] = 3;
*(ptr+2) = 5;
ptr[1] = 3;一段神奇的代码
1
2
3
4
5
6// error, 申请数组变量大小不可以是变量
int size = 5;
int a[size];
// correct
static const int size = 5;
int a[size];
mem in stack/heap
- C++ 程序中的内存分为两个部分:
- 栈(stack):在函数内部声明的所有变量都将占用栈内存。
- 堆(heap):这是程序中未使用的内存,在程序运行时可用于动态分配内存
- 在 C++ 中,您可以使用特殊的运算符(new)为给定类型的变量在运行时分配堆(heap)内的内存,这会返回所分配的空间地址。
- 如果您不再需要动态分配的内存空间,可以使用 delete 运算符,删除之前由 new 运算符分配的内存
标准库的数组
1 |
|
什么是vector?
向量(Vector)是C++中的一种数据结构,确切的说是一个类。一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。
vector是一个能够存放任意类型的动态数组
。使用vector之前要导入头文件
1
其中vector是一个定义于namespace std内的模板(template):
1
2
3
4namespace std{
template <class T, class Allocator = allocator<T> >
class vector;
}vector中的元素可以使任意类型,但是必须能够赋值和拷贝。第二个参数可有可无,是用来定义内存模型(memory model),缺省的内存模型是C++标准库提供的allocator。
容器特性
1.顺序序列
- 顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。
2.动态数组
- 支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。操供了在序列末尾相对快速地添加/删除元素的操作。
3.能够感知内存分配器的(Allocator-aware)
- 容器使用一个内存分配器对象来动态地处理它的存储需求。
常用函数:
构造函数
函数名 | 说明 |
---|---|
vector() | 创建一个空vector |
vector(int nSize) | 创建一个vector,元素个数为nSize |
vector(int nSize,const t& t) | 创建一个vector,元素个数为nSize,且值均为t |
vector(const vector&) | 复制构造函数 |
vector(begin,end) | 复制[begin,end)区间内另一个数组的元素到vector中 |
demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using namespace std;
void show(vector<int> v) {
cout << "vector : ";
for (auto val : v) {
cout << val << " ";
}
cout << endl;
}
int main() {
vector<int> v; //定义一个空 vector 对象
vector<int> v1(10); //定义一个具有 10 个元素的 vector 对象(int 型元素默认初始化为 0)
vector<int> v2(3,5); //v = { 5, 5, 5 }
vector<int> v3(v); //v1 = v
vector<int> v4 = { 1, 2, 3 };
vector<int> v5 = v;
show(v);
show(v1);
show(v2);
show(v3);
show(v4);
show(v5);
}结果如下
1
2
3
4
5
6vector :
vector : 0 0 0 0 0 0 0 0 0 0
vector : 5 5 5
vector :
vector : 1 2 3
vector :
增加函数
函数名 | 说明 |
---|---|
void push_back(const T& x) | 向量尾部增加一个元素X |
iterator insert(iterator it,const T& x) | 向量中迭代器指向元素前增加一个元素x |
iterator insert(iterator it,int n,const T& x) | 向量中迭代器指向元素前增加n个相同的元素x |
iterator insert(iterator it,const_iterator first,const_iterator last) | 向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据 |
1 |
|
- 结果如下
1
2
3
4vector : 1 2 3 4
vector : 4 1 2 3 4
vector : 0 0 0 4 1 2 3 4
vector : 1 2 3 4
删除函数
函数名 | 说明 |
---|---|
iterator erase(iterator it) | 删除向量中迭代器指向元素 |
iterator erase(iterator first,iterator last) | 删除向量中[first,last)中元素 |
void pop_back() | 删除向量中最后一个元素 |
void clear() | 清空向量中所有元素 |
1 |
|
- 结果如下
1
2
3
4vector : 1 2 3 4
vector : 2 3 4
vector : 4
vector :
遍历函数
函数名 | 说明 |
---|---|
reference at(int pos) | 返回pos位置元素的引用 |
reference front() | 返回首元素的引用 |
reference back() | 返回尾元素的引用 |
iterator begin() | 返回向量头指针,指向第一个元素 |
iterator end() | 返回向量尾指针,指向向量最后一个元素的下一个位置 |
reverse_iterator rbegin() | 反向迭代器,指向最后一个元素 |
reverse_iterator rend() | 反向迭代器,指向第一个元素之前的位置 |
1 |
|
- 结果如下
1
2
3
4
5
63
3
1
5
1
5
判断函数
函数名 | 说明 |
---|---|
bool empty() const | 判断向量是否为空,若为空,则向量中无元素 |
1 |
|
- 结果如下
1
2v1 is empty : 0
v2 is empty : 1
大小函数
函数名 | 说明 |
---|---|
int size() const | 返回向量中元素的个数 |
int capacity() const | 返回当前向量张红所能容纳的最大元素值 |
int max_size() const | 返回最大可允许的vector元素数量值 |
1 |
|
- 结果如下
1
2
3size : 5
capacity : 5
max_size : 4611686018427387903
其他函数
函数名 | 说明 |
---|---|
void swap(vector&) | 交换两个同类型向量的数据 |
void assign(int n,const T& x) | 设置向量中第n个元素的值为x |
void assign(const_iterator first,const_iterator last) | 向量中[first,last)中元素设置成当前向量元素 |
小技巧
使用 C++ 11 新特性访问
1 | vector<int> v = { 1, 2, 3, 4 }; |
查找一个元素是否在 vector 中
1 | vector<int> v = { 1, 2, 3, 4 }; |
倒序遍历
1 | vector<int> nums = {1,2,3,4,5,6,7}; |
Vector 和 数组的区别
- 数组是c++中类似vector的数据结构,它们都可以对一种类型进行储存,既都是容器。虽说两者有相似之处,但也有显著的区别,c++ primer的作者说到,在实际的编程中,我们作为程序员应该避免用到低级数组和指针,而更应该多用高级的vector和迭代器。
一些使用 vector 的建议
- 好好使用
reserve
方法(用于申请足够的空间来储存变量),可以有效的减少容量不足->重新申请空间->copy
的过程