C++ stl库介绍一 vector
在这里我先假定读者具有一定的代码阅读量,起码可以和我处在同一档次上.因此看下面的部分代码,不需要我加注释.
Vector是我最早接触的stl容器,最开始使用的使用,一直是当做数组的替代品使用,但是也以为vector是C++用包装好的数组,结果,后来发现在容器(container)中还有一类array
Vector放入中文词典中,叫做矢量.在stl中,解释为”Vectors are sequence containers representing arrays that can change in size.即可用来代表数组的可变长度序列容器.有上述的解释中,我们可以了解到vector具有以下三个特性:
序列化
你可以把vector理解成连续的内存队列,和数组类似,他是一个严格连续的队列.里面的元素都是紧密排布在连续的内存上.
数组特性
允许直接访问内部的元素(使用[]符号访问),由于代表数组,允许使用指针(接口)访问他.
动态增长:
同时它是动态增长的,只要编译器能够提供足够长的内存段,就可以继续动态增长.
在这里要聊一聊vector的动态内存机制.vector内存空间只会增长,不会减小.在这里我援引C++ Primer:
"为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储。设想一下,当vector添加一个元素时,为了满足连续存储这个特性,都需要重新分配空间、拷贝元素、撤销旧空间,这样性能难以接受。因此STL实现者在对vector进行内存分配时,其实际分配的容量要比当前所需的空间多一些。就是说,vector容器预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素重新分配整个容器的内存空间。"
在上述的引述中没有提到的一点是.在重新申请的时,优先在原地扩展。比如,原保留空间是32字节,那么会先看看直接在这32个字节后再分配32字节是否可能。如果成功,那么就不用发生原vector空间内的数据到新vector空间的搬移。但是,这是有可能失败的,失败的原因一般是后续32个字节中,有部分或全部,已经被别的对象占用了,不够组成64字节的连续空间。这时候,在堆上找到一个新地址,这个地址有64字节的连续空间,并将原来vector中的内容复制过来,并且释放原来的空间。我们可以使用 allocate函数查看当前编译器为vector准备的可以容纳的元素的总个数.
2.vector内的(可使用)元素
元素类型 | 声明 | |
value_type | 第一个模板类参数存放 值(value) | |
allocator_type | 第二个模板类参数 (Alloc) | defaults to:allocator<value_type> |
reference | 值的引用(value&) | allocator_type::reference |
const_reference | 值的常引用 | const_reference |
pointer | 指向值的指针 | allocator:value_type* |
const_pointer | 指向某个值的常指针 | for the default allocator: const value_type* |
iterator | 迭代器 | convertible to const_iterator |
const_iterator | 常迭代器 | |
reverse_iterator | 逆向迭代器 | |
const_reverse_iterator | 常逆向迭代器 | |
difference_type | a signed integral type, identical to: | usually the same as ptrdiff_t |
size_type | vector对象的长度 | usually the same as size_t |
在上面的表格中有几个项需要借用allocator来说明.因此我在这里提一下在这里要提一下allocator, 它提供类型化的内存分配以及对象的分配和撤销。allocator类将对象分配和对象构造分开。当allocator对象分配内存的时候,它会分配适当大小并排列成保存给定类型对象的空间。在stl的容器类,allocator是一个非常重要的存在.容器类中的元素都是有allocator来提供的.
Allocaor内的元素:
member | definition inallocator | represents |
value_type | T | 元素类型 |
pointer | T* | 元素的指针 |
reference | T& | 元素的引用 |
const_pointer | const T* | 指向元素的常引用 |
const_reference | const T& | 元素的引用 |
size_type | 容量 | |
difference_type | 两个指针的间距,可以理解为返回的统一容器中两个元素之间偏移的大小 | |
member class | Its member type other is the equivalent allocator type to allocate elements of type Type 一个查询器或者说转换器,它查询的内容是:对给定的分配器allocator<T>如何得到和T相关的类型U的分配器类型 |
感兴趣的朋友可以参见一下的网页http://www.cplusplus.com/reference/memory/allocator/
Vector的函数表我并不想过多的赘述,在这里给一个我常用的查询网址:
http://www.cplusplus.com/reference/vector/vector/
但是还是有几个函数要重点说说:
1. 构造函数:
default (1) | explicit vector (const allocator_type& alloc = allocator_type()); |
fill (2) | explicit vector (size_type n); vector (size_type n, const value_type& val, const allocator_type& alloc = allocator_type()); |
range (3) | template <class InputIterator> vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); |
copy (4) | vector (const vector& x); vector (const vector& x, const allocator_type& alloc); |
move (5) | vector (vector&& x); vector (vector&& x, const allocator_type& alloc); |
initializer list (6) | vector (initializer_list<value_type> il, const allocator_type& alloc = allocator_type()); |
在这里我用代码来进行表述:
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> first;
std::vector<int> second (4,100); // second中将有4个一样100
std::vector<int> third(second.begin(),second.end()); // 使用迭代器进行初始化
std::vector<int> fourth (third); //拷贝第三个
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
//使用数组复制
std::cout << "Thecontents of fifth are:";
for (std::vector<int>::iteratorit = fifth.begin(); it != fifth.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
2vector::end()
返回一个迭代器指向vector最后一个元素之后的位置,注意这个位只是一个理论元素。它不指向任何元素,因此不得解除引用。
常见的用法是与begin共用遍历整个vector
// vector::begin/end #include <iostream> #include <vector> int main () { std::vector<int> myvector; for (int i=1; i<=5; i++) myvector.push_back(i); std::cout << "myvector contains:"; for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it) std::cout << ' ' << *it; std::cout << '\n'; return 0; }
3,vector::data()
返回一个指向头一个元素的allocator:value_type*,即指向第一个元素的指针
// vector::data
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector (5);
int* p = myvector.data();
*p = 10;
++p;
*p = 20;
p[2] = 100;
std::cout << "myvector contains:";
for (unsigned i=0; i<myvector.size(); ++i)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}