对vector内部结构的解析(一)

来源:互联网 发布:深圳java自行车 编辑:程序博客网 时间:2024/06/04 19:33

     vector想必是每个C++程序员耳熟能详的数据结构 , 在实际编程中 , 使用vector尽管从效率上讲没有内置类型的数组高 , 但却不需要程序员自己管理内存 , 也不用担心数组的大小不够 , 还能进行各种各样的算法 , 还可以用迭代器实现与其它数据结构的交替 , 牺牲一点点效率换取这么多好处也是值得的。

    下面我们对vector的内部数据结构进行解析 , 我们都知道vector是能够动态增长的 , 至于具体是怎么增长的 , 可写一个简单的程序试验一下:

vector<int> vi;    //已导入vector头文件cout << "number of member:" << vi.size()    //该函数返回vector中元素个数<< "  capacity:" << vi.capacity() << endl;    //该函数返回vector最大容量for(int i = 0 ; i != 20 ; i++){vi.push_back(i);cout << "number of member:" << vi.size()<< "  capacity:" << vi.capacity() << endl;}
    这个程序的输出如下:

number of member:0  capacity:0
number of member:1  capacity:1
number of member:2  capacity:2
number of member:3  capacity:4
number of member:4  capacity:4
number of member:5  capacity:8
number of member:6  capacity:8
number of member:7  capacity:8
number of member:8  capacity:8
number of member:9  capacity:16
number of member:10  capacity:16
number of member:11  capacity:16
number of member:12  capacity:16
number of member:13  capacity:16
number of member:14  capacity:16
number of member:15  capacity:16
number of member:16  capacity:16
number of member:17  capacity:32
number of member:18  capacity:32
number of member:19  capacity:32
number of member:20  capacity:32


    从输出我们就能看到很多信息 , 首先 , 用默认构造函数建立的vector的初始容量为0 , 当添加第一个元素时容量变为1 , 同时元素个数也为1 , 之后我们能看到每一次动态增长容量都会翻倍 , 并且当内部元素个数小于等于容量时 , vector都不会增长 , 这样我们就可以得出结论 , 当向vector添加元素时 , 如果size() == capacity(),则把容量乘2 , 然后在已分配的位置根据参数初始化(各种参数构造函数 , 拷贝构造函数 , 移动构造函数),容量够的话 , 就直接在下个位置初始化。为了更进一步证实我们的结论 , 运行下述程序:(接着上一段程序)

vi.reserve(40);    //该函数把最大容量设为参数值cout << "number of member:" << vi.size()<< "  capacity:" << vi.capacity() << endl;for(int i = 20 ; i != 41 ; i++){vi.push_back(i);cout << "number of member:" << vi.size()    << "  capacity:" << vi.capacity() << endl;}

该程序输出如下:

number of member:20  capacity:40
number of member:21  capacity:40
number of member:22  capacity:40
number of member:23  capacity:40
number of member:24  capacity:40
number of member:25  capacity:40
number of member:26  capacity:40
number of member:27  capacity:40
number of member:28  capacity:40
number of member:29  capacity:40
number of member:30  capacity:40
number of member:31  capacity:40
number of member:32  capacity:40
number of member:33  capacity:40
number of member:34  capacity:40
number of member:35  capacity:40
number of member:36  capacity:40
number of member:37  capacity:40
number of member:38  capacity:40
number of member:39  capacity:40
number of member:40  capacity:40
number of member:41  capacity:80
    当最大元素个数超过40时 , 容量变为80 , 可见确实是翻倍的增长。在运行下面一段程序:

vi.resize(60);    //该函数把vector的元素个数设为参数值cout << "number of member:" << vi.size()<< "  capacity:" << vi.capacity() << endl;vi.resize(35);cout << "number of member:" << vi.size()<< "  capacity:" << vi.capacity() << endl;

输出如下:

number of member:60  capacity:80
number of member:35  capacity:80

    从输出可以看出 , 当把设置元素个数大于先有个数时 , 会调用默认构造函数构造不够的元素 , 所以没有默认构造函数的类无法这样使用这个默认参数形式 , 应该在第二个参数位置传入构造函数 , 同样的 , 当设置元素个数小于先有个数时 , 会对多出来的元素调用析构函数 , 对于内置类型 , 并不会破坏它的值 , 只是当它不存在(即还是能被访问到的)。

    为什么说尽量不要在vector中间插入元素 , 下面我们来看一个简单的小程序:

time_t t = time(0);vector<int> vi;cout << endl;for(int i = 0 ; i < 300000000 ; i++){vi.push_back(i);}cout << (time(0) - t) << endl;t = time(0);for(int i = 0 ; i < 30 ; i++){vi.insert(vi.begin() , i);}cout << (time(0) - t) << endl;    //该程序展示了添加3亿个元素和插入30个元素时间比较
输出为:

8
6

    (不同机器或编译器结果不同 , 但大致比例相同)

    从上述结果可以看出插入操作的效率是非常低的 , 至于原因我们在下一篇分析。对vector内部结构的解析(二)


1 0
原创粉丝点击