C++ STL vector 内存分配

vector为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储。

当vector添加一个元素时,为了满足连续存放这个特性,都需要重新分配空间、拷贝元素、撤销旧空间,这样性能难以接受。因此STL实现者在对vector进行内存分配时,其实际分配的容量要比当前所需的空间多一些。就是说,vector容器预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素重新分配整个容器的内存空间。

 

通过下面代码可以更清楚的看到vector在push_back、insert、reserve、resize时占用内存的变化。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include<cstdio>
#include<iostream>
#include<vector>
#include<iterator>
using namespace std;
 
//打印vector元素
#define Display(v) copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); cout<<endl;
/*
 * size()返回当前vector所容纳元素的数目
 * max_size()函数返回当前vector所能容纳元素数量的最大值(包括可重新分配内存)
 * capacity()函数返回当前vector在重新进行内存分配以前所能容纳的元素数量
 */
#define PrintSC(v) printf("size:%d\tcapacity:%d\t\n", v.size(), v.capacity());
 
int main(){
    int i;
 
    printf("%d\t%d\n", sizeof(int), sizeof(double)); //输出int和double的字节数
    //输出:4  8
 
    int data_int[5] = {1,2,3,4,5};
    double data_double[5] = {1.0,2.0,3.0,4.0,5.0};
    vector<int> v0, v1, v2; //空的vector
    vector<int> vi(data_int, data_int+5);
    vector<double> vd(data_double, data_double+5);
 
    cout<<v0.max_size()<<endl;
    //输出:1073741823
    //说明vector可分配的内存大小为 1073741823*4B 即为 4GB
    //max_size()源码为:size_type max_size() const { return static_cast<size_type>(-1) / sizeof(value_type); }
 
    vector<int>::iterator it0;
    for(i=0; i<5; i++){
        v0.push_back(i);
        PrintSC(v0);
        for(it0=v0.begin(); it0!=v0.end(); it0++)
            printf("%p ", it0);
        printf("\n");
    }
    //输出:   size:1  capacity:1
    //      00A72F00
    //      size:2  capacity:2
    //      00A72C38 00A72C3C
    //      size:3  capacity:4
    //      00A72F00 00A72F04 00A72F08
    //      size:4  capacity:4
    //      00A72F00 00A72F04 00A72F08 00A72F0C
    //      size:5  capacity:8
    //      00A72C38 00A72C3C 00A72C40 00A72C44 00A72C48
    //说明使用push_back时,当size>capacity时,vector分配空间是成倍增长的,
    //而且为了保证能有连续的内存空间,重分配空间可能造成元素存储位置改变
 
 
    vector<int>::iterator it1;
    v1.reserve(3);
    PrintSC(v1);
    for(i=0; i<5; i++){
        it1 = v1.begin(); //每次必须重新定位,因为有可能插入元素有可能造成重新分配内存空间,原指针作废
        v1.insert(it1, 1, i);
        PrintSC(v1);
        for(it1=v1.begin(); it1!=v1.end(); it1++)
            printf("%p ", it1);
        printf("\n");
    }
    //输出:   size:1  capacity:3
    //      00482F00
    //      size:2  capacity:3
    //      00482F00 00482F04
    //      size:3  capacity:3
    //      00482F00 00482F04 00482F08
    //      size:4  capacity:6
    //      00482C60 00482C64 00482C68 00482C6C
    //      size:5  capacity:6
    //      00482C60 00482C64 00482C68 00482C6C 00482C70
    //说明使用insert的时候与push_back分配内存类似,都是不足时以两倍原大小重分配,
    //如果使用了reserve,则会预留指定大小连续空间
 
 
    v1.resize(7, -1);
    PrintSC(v1);
    for(it1=v1.begin(); it1!=v1.end(); it1++)
        printf("%p ", it1);
    printf("\n");
    v1.resize(3, -1);
    PrintSC(v1);
    for(it1=v1.begin(); it1!=v1.end(); it1++)
        printf("%p ", it1);
    printf("\n");
    v1.resize(13, -1);
    PrintSC(v1);
    for(it1=v1.begin(); it1!=v1.end(); it1++)
        printf("%p ", it1);
    printf("\n");
    v1.resize(3, -1);
    PrintSC(v1);
    for(it1=v1.begin(); it1!=v1.end(); it1++)
        printf("%p ", it1);
    printf("\n");
    //输出:   size:7  capacity:10
    //      005A2C80 005A2C84 005A2C88 005A2C8C 005A2C90 005A2C94 005A2C98
    //      size:3  capacity:10
    //      005A2C80 005A2C84 005A2C88
    //      size:13 capacity:13
    //      005A2CB0 005A2CB4 005A2CB8 005A2CBC 005A2CC0 005A2CC4 005A2CC8 005A2CCC 005A2CD0 005A2CD4 005A2CD8 005A2CDC 005A2CE0
    //      size:3  capacity:13
    //      005A2CB0 005A2CB4 005A2CB8
    //说明使用resize的时候当new_size大于当前capacity的时候,会发生内存重分配。
 
    Display(v0);
    PrintSC(v0);
    v0.clear(); //删除当前vector中的所有元素
    Display(v0);
    PrintSC(v0);
    //输出:   0 1 2 3 4
    //      size:5  capacity:8
    //
    //      size:0  capacity:8
    //说明clear函数不能回收vector占用的内存空间
 
    return 0;
}

  另外,resize的时候内存分配机制还有些疑问,参加这个讨论 http://bbs.csdn.net/topics/390739204

C++ STL vector 内存分配,布布扣,bubuko.com

C++ STL vector 内存分配

上一篇:Java将对象保存到文件中/从文件中读取对象


下一篇:C++ builder的文件操作