std::vector


今天做题的时候用到了std::vector, 这里记录一下,内容主要来自《C++标准库》这本书。

根据C++standard,vector是以dynamic array实现的。在使用之前需要包含头文件<vector>

#include <vector>

大小和容量

Vector本身效率很高,但代价是需要分配出更大的空间。所以相比起一些手动算法,在空间控制上可能没那么理想。

想要获得当前vector内的元素个数,可以使用size()方法。

//std::vector<int> coll
coll.size()

可以直接返回一个整数,其大小是这个vector内的元素个数。

如果这个vector是空的,则coll.empty()会返回true

除此之外,还涉及一个问题就是一个vector的容量(Capacity)。特别是如果你需要使用频繁、大规模地使用Vector可以改变长度这个特性的话,尤其需要注意。因为vector在运行过程中可能会重新分配空间,这将导致地址发生变化,如果不做任何措施,原有的引用、指针和迭代器等都可能会失效。而且重新分配内存很耗时间。序偶一你需要好好考虑容量问题。

​ 你可以使用reserve()来保留适当的容量以避免因容量不够而重新分配内存:

std::vector<int> v;
v.reserve(80);//reserve memroy for 80 elements

但vector不能像string那样用reserve()来减小容量。vector的容量不能缩减(但长度可以缩减)。如果给reserve()的参数小于当前容量,什么也不会发生。

几种比较常见的操作

c.empty(): 返回是否为空

c.size():返回元素个数

c.max_size()发挥元素个数之最大可能量

c.assign(n, elem): 复制n个elem赋给C

c.assign(begin, end): 将区间[begin, end)内的元素赋给c

c.assign(initlist): 用初始值列表给c赋值

c1.swap()swap(c1, c2): 置换c1和c2的数据

访问操作

c[index](不检查范围)或c.at(index)(检查范围)

c.front()返回首元素

c.back()返回末尾元素

迭代器相关

c.begin(), c.end()返回一个random-access iterator指向首、尾元素

c.cbegin(), c.cend() 返回一个const ramdom-access iterator指向首、尾元素

c.rbegin(), c.rend(), c.crbegin(), c.crend()返回反向迭代的首尾元素迭代器

利用迭代器的一些操作

c.push_back(elem): 附加一个elem拷贝于末尾

c.pop_back(): …上面的逆操作

c.insert()支持以下参数列表:

pos, elem

pos, n, elem

pos, begin, end

pos, initlist

c.emplace(pos, args...)

e.emplace_back(args...)

c.erase(pos): 移除pos这个iterator上的元素

e.erase(begin, end): 移除从begin到end中间所有的元素

所以如果你想移除“与某个值相等”的元素,虽然vector没有直接提供,但是可以通过其他一些辅助函数来实现。比如,你可以通过下面这个语句将所有值为val的元素移除

#include<algorithm>//提供remove函数的声明
std::vector<elem> coll;
...
//remove al elements with value val
coll.erase(remove(coll.begin(), coll.end(), val), coll.end());

如果你想只删除值一样的第一个元素:

std::vector<elem> coll;
...
std::vector<elem>::iterator pos;
pos=find(coll.begin(), coll.end(), val);
if(pos!=coll.end())
{
    coll.erase(pos);
}

### 关于Vector的异常处理

除非用户自定义了新的异常,或者标准异常(比如bad_alloc), c.at()是唯一一个标准认可的可以抛出异常的函数. 其他的函数,基本都不会抛出异常,甚至标准还保证类似push_back()这样的方法绝对不会抛出异常。