怎样将vector当作一个数组来使用,在C++标准化后,我们都致力于使用vector来代替数组,但不可不承认的是,老的C版本的API还是存在的,那么我们怎么用vector来当作是数组来用。
简单的,看一个简单的例子。
void doSomething(const int* p, size_t size)
如果我们想将vector传入上面的函数,则
vectorvec; doSomething(&vec[0], vec.size());
上面的调用在很多时候是没有问题的,但是如果当vector是空的时候,&vec[0] 会试图产生一个指针,并且这个指针指向的内存是不存在的,我们通常用到的解决方法是
vectorvec; if(vec.empty()) { return; } doSomething(&vec[0], vec.size());
你是不是听过一种说法,在容器中,迭代器就相当于是容器的指针。因此可能会产生一种想用vec.begin() 来代替 &vec[0] 的想法。因为 vec.begin()返回的就是 vec的首个元素的迭代器。通常情况下,这个是没错的。
但我们不能不明确的一件事是,vec.begin()返回的是迭代器,不是指针。上面的等价代替的应该如下, &*vec.begin(),直观一点就是 &(*vec.begin());这样才会产生和&vec[0]相同的指针。
如果你周围的环境告诉你要使用 vec.begin()来代替&vec[0];那么,坦率的讲,或许你该考虑换个环境了。
但是相对与string来说就没有这么麻烦了,因为string有成员函数 c_str();这个成员函数我们经常使用。
void doSomething(const char* p) string s; doSomething(s.c_str());
上面的两个函数的传值不知道你有没有注意到,传值都是const类型,不允许修改的。这主要是因为,如果我们在CAPI中改变原有容器的值,那肯定是没问题的,但是如果我们试图在vector未使用的容量中创建一个元素,那么vec的内部会变得不一致。因为无法知道vec的大小,vec.size()将产生不正确的结果。
同样的,假设传进去的vector的capacity 和 size 一样的话,在CAPI内部对vector创建新元素时,会出现越界。
但这样并不是没有办法的,因为vector和数组的内存布局是可以兼容的,那么我们在初始化容器的时候,将容器的存储区域传给C API。
size_t fillArray(double* pArray, size_t arraySize); vectorvec[maxSize]; vec.resize(fillArray(&vec[0], vec.size())));
上面的代码是先用fillArray这个API向vec中写入数据,然后将vec的大小改变为这个API写入数据的大小。
同时,我们前面已经知道了stl容器之间是可以进行数据的拷贝的,比如:
vectorvd(vec.begin(), vec.end()) list l(vec.begin(), vec.end()) ...
因此,我们将数据拷贝到最终期望写入的STL容器中这个方案是可行的。
2、swap函数的使用技巧想象一种使用场景,我们首先有个capacity和size均为10000的容器,但是后来因为满足条件对该容器进行元素的删除,现在只剩下100个元素,那也就意味这有9900个元素的空间是没有被使用的,但是却被容器占用,也就是造成了资源浪费,那么我们能够通过什么样的方式释放这些没有被使用的内存呢?
- 首先我们想到的可能就是最基本的方法,重新创建一个临时的capacity为100的同类型容器,暂存数据,等将原先容器的大小改变为100之后进行赋值。但是该怎样改变原先容器的容量呢?
容器提供了很多的类似pop_back、earse、clear 这样的成员函数来删除容器中的元素,但是这些成员函数能够删除容器中的成员元素,但是并不能改变容器的容量大小。
vectorvec; vec.reaser(100); for(int index = 0; index < 10; ++index) { vec.push_back(index); } count << vec.size() << " " << vec.capacity() << endl; //10 100 vec.earse(vec.begin()); count << vec.size() << " " << vec.capacity() << endl; //9 100 vec.pop_back(); count << vec.size() << " " << vec.capacity() << endl; //8 100 vec.clear(); count << vec.size() << " " << vec.capacity() << endl; //0 100
从上面的例子我们能够看出,这些成员函数并不能改变容器的容量。
幸运的是,在vec的模版类中找到了一个函数,shrink_to_fit()成员方法。该成员方法的功能是将当前vec的容量缩减至和该vec实际存储的元素的数量相等。
vec.reaser(100);
for(int index = 0; index < 10; ++index)
{
vec.push_back(index);
}
count << vec.size() << " " << vec.capacity() << endl; //10 100
vec.shrink_to_fit();
count << vec.size() << " " << vec.capacity() << endl; //10 10
- 利用swap函数除去多余的空间
vectorv1; vector v2{v1.begin(), v1.end()};
在容器拷贝的时候,容器中未被占用的部分是不会被拷贝的,也就是说,拷贝之后的容器的容量是和被拷贝容器的size是一样的。
然后将这两个容器使用swap函数交换。
v2.swap(v1);
写作简单的方法:
vector(v1).swap(v1); //string s; ... //string(s).swap(s); //对s做 shrink_to_fit() 操作
- 有了上面的例子,我们也就能够顺理得章的有了下面的方法:
vector().swap(v1);
用一个空的vector容器去和v1进行swap操作,按照上面的经验结果,我们能够得出,这样的目的是能够将容器v1清空,并将其容量也改为0。



