vector的内存分配机制分析

Posted 聚沙成塔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vector的内存分配机制分析相关的知识,希望对你有一定的参考价值。

该程序初步演示了我对vector在分配内存的时候的理解。可能有误差,随着理解的改变,改代码可以被修改。

  1 /*
  2 功能说明:
  3     vector的内存分配机制分析。
  4 代码说明:
  5     vector所管理的内存地址是连续的。程序在不断的push_back的过程中,如果当前所管理的内存不能装下新的元素的时候,程序会创建更大的地址连续的空间来保存更多的元素。
  6     这种机制会引起大量的无用的复制和删除操作。如果vector的元素为类结构的时候,他就会有很多临时变量产生。通过复制构造函数和析构函数,可以看到这些操作。
  7 实现方式:
  8     
  9 限制条件或者存在的问题:
 10  11 */
 12 #include <iostream>
 13 #include <string>
 14 #include <vector>
 15 
 16 #include <windows.h>
 17 
 18 using namespace std;
 19 
 20 class CData
 21 {
 22 public:
 23     CData()
 24     {
 25         sequence = 0;
 26         this->remark = "default string";
 27 
 28         cout << "CData()\\t" << toString() <<"\\t"<< this << endl;
 29     }
 30 
 31     CData(int i,string &s)
 32     {
 33         this->sequence = i;
 34         this->remark = s;
 35 
 36         cout << "CData(int i,string &s)\\t" << toString() << "\\t" << this << endl;
 37     }
 38 
 39     CData(const CData &data)
 40     {
 41         this->sequence = data.sequence;
 42         this->remark = data.remark;
 43 
 44         cout << "CData(const CData &data)\\t" << toString() << "\\t" << this << endl;
 45     }
 46 
 47     CData operator = (const CData &data)
 48     {
 49         this->sequence = data.sequence;
 50         this->remark = data.remark;
 51 
 52         cout << "CData operator = (const CData &data)\\t" << toString() << "\\t" << this << endl;
 53 
 54         return *this;
 55     }
 56 
 57     void setSequence(const int i)
 58     {
 59         this->sequence = i;
 60     }
 61 
 62     void setRemark(const string &s)
 63     {
 64         this->remark = s;
 65     }
 66 
 67     string toString() const
 68     {
 69         char tmp[2048] = { 0 };
 70         sprintf(tmp, "[sequence:%d | remark:%s]", this->sequence, this->remark.c_str());
 71 
 72         //此处应该有内存复制操作,所以不用担心返回后tmp数组所指向的内存被修改或者不存在的情况。
 73         return tmp;
 74     }
 75 
 76     ~CData()
 77     {
 78         cout << "~CData()\\t" << this << endl;
 79     }
 80 protected:
 81 private:
 82     int sequence;
 83     string remark;
 84 };
 85 
 86 int main(int argc, char **argv)
 87 {
 88     cout << "process begin at " << (void*)&main << endl;
 89 
 90     string str = "baby_test";
 91     CData data1(1, str);
 92     CData data2(2, str);
 93     CData data3(3, str);
 94     CData data4(4, str);
 95     CData data5(5, str);
 96     CData data6(6, str);
 97     CData data7(7, str);
 98     CData data8(8, str);
 99     CData data9(9, str);
100     CData data10(10, str);
101 
102     cout << "push CData to vector" << endl;
103     vector<CData> vec_data;
104     cout << "max size of vector<CData> is " << vec_data.max_size() << endl;
105     cout << "size of vector<CData> is " << vec_data.size() << endl;
106     
107     cout << "****************vec_data.push_back(data1)" << endl;
108     vec_data.push_back(data1);
109     Sleep(2 * vec_data.size());
110     
111     cout << "****************vec_data.push_back(data2)" << endl;
112     vec_data.push_back(data2);
113     Sleep(2 * vec_data.size());
114     
115     cout << "****************vec_data.push_back(data3)" << endl;
116     vec_data.push_back(data3);
117     Sleep(2 * vec_data.size());
118 
119     cout << "****************vec_data.push_back(data4)" << endl;
120     vec_data.push_back(data4);
121     Sleep(2 * vec_data.size());
122 
123     cout << "****************vec_data.push_back(data5)" << endl;
124     vec_data.push_back(data5);
125     Sleep(2 * vec_data.size());
126 
127     cout << "****************vec_data.push_back(data6)" << endl;
128     vec_data.push_back(data6);
129     Sleep(2 * vec_data.size());
130 
131     cout << "****************vec_data.push_back(data7)" << endl;
132     vec_data.push_back(data7);
133     Sleep(2 * vec_data.size());
134 
135     cout << "****************vec_data.push_back(data8)" << endl;
136     vec_data.push_back(data8);
137     Sleep(2 * vec_data.size());
138 
139     cout << "****************vec_data.push_back(data9)" << endl;
140     vec_data.push_back(data9);
141     Sleep(2 * vec_data.size());
142 
143     cout << "****************vec_data.push_back(data10)" << endl;
144     vec_data.push_back(data10);
145     Sleep(2 * vec_data.size());
146 
147     // 程序到此为止,日志显示的比较怪异。
148     // 具体来说,就是,将CData对象push到向量中的时候,程序会通过复制构造函数,创建一些临时变量。
149     // 创建临时变量的原因分析:这可能与vector的内存分配方式有关。vector所创建的对象的内存的地址是连续的。
150     // 当当前的vector所拥有内存不能装入新的元素的时候,程序会创建开辟新的地址连续的空间,并将原来地址中的元素全部复制一份,保存到新的地址中。然后在删除原来的地址中的对象。
151 
152     cout << "===============show vector by iterator" << endl;
153     for (vector<CData>::iterator itr = vec_data.begin(); itr != vec_data.end(); itr++)
154     {
155         // 显示的地址信息,是最后一次push的时候所复制的对象的地址。
156         cout << "address of itr is " << &(*itr) << "\\tvalue is " << itr->toString() << endl;
157     }
158 
159     cout << "===============clear vector 1" << endl;
160     // vector中的元素不是指针,此处的清理,会调用析构函数。
161     vec_data.clear();
162 
163     // 根据上面的分析,再次测试。
164     // 本次测试是在将元素push到vector中之前,先为vector申请“足够大”的内存。
165     vec_data.reserve(20);
166     cout << "size of vector<CData> is " << vec_data.size() << endl;
167     cout << "capacity of vector<CData> is " << vec_data.capacity() << endl;
168 
169     cout << "****************vec_data.push_back(data1)" << endl;
170     vec_data.push_back(data1);
171     Sleep(2 * vec_data.size());
172 
173     cout << "****************vec_data.push_back(data2)" << endl;
174     vec_data.push_back(data2);
175     Sleep(2 * vec_data.size());
176 
177     cout << "****************vec_data.push_back(data3)" << endl;
178     vec_data.push_back(data3);
179     Sleep(2 * vec_data.size());
180 
181     cout << "****************vec_data.push_back(data4)" << endl;
182     vec_data.push_back(data4);
183     Sleep(2 * vec_data.size());
184 
185     cout << "****************vec_data.push_back(data5)" << endl;
186     vec_data.push_back(data5);
187     Sleep(2 * vec_data.size());
188 
189     cout << "****************vec_data.push_back(data6)" << endl;
190     vec_data.push_back(data6);
191     Sleep(2 * vec_data.size());
192 
193     cout << "****************vec_data.push_back(data7)" << endl;
194     vec_data.push_back(data7);
195     Sleep(2 * vec_data.size());
196 
197     cout << "****************vec_data.push_back(data8)" << endl;
198     vec_data.push_back(data8);
199     Sleep(2 * vec_data.size());
200 
201     cout << "****************vec_data.push_back(data9)" << endl;
202     vec_data.push_back(data9);
203     Sleep(2 * vec_data.size());
204 
205     cout << "****************vec_data.push_back(data10)" << endl;
206     vec_data.push_back(data10);
207     Sleep(2 * vec_data.size());
208 
209     cout << "===============show vector by iterator 2" << endl;
210     for (vector<CData>::iterator itr = vec_data.begin(); itr != vec_data.end(); itr++)
211     {
212         cout << "address of itr is " << &(*itr) << "\\tvalue is " << itr->toString() << endl;
213     }
214 
215     // 上面的日志信息显示。vector开始已经有了足够大的地址空间来保存这10个变量,所以,他就不会再频繁创建新的内存地址和创建新对象了。
216     // 这样的方式,可以节省很多的系统开销。
217 
218     cout << "===============clear vector 2" << endl;
219     // vector中的元素不是指针,此处的清理,会调用析构函数。
220     vec_data.clear();
221 
222     cout << "======================end of process" << endl;
223 
224     return 0;
225 }
View Code

程序的结果:
process begin at 00D1173A
CData(int i,string &s)  [sequence:1 | remark:baby_test] 00CAFAD0
CData(int i,string &s)  [sequence:2 | remark:baby_test] 00CAFAA8
CData(int i,string &s)  [sequence:3 | remark:baby_test] 00CAFA80
CData(int i,string &s)  [sequence:4 | remark:baby_test] 00CAFA58
CData(int i,string &s)  [sequence:5 | remark:baby_test] 00CAFA30
CData(int i,string &s)  [sequence:6 | remark:baby_test] 00CAFA08
CData(int i,string &s)  [sequence:7 | remark:baby_test] 00CAF9E0
CData(int i,string &s)  [sequence:8 | remark:baby_test] 00CAF9B8
CData(int i,string &s)  [sequence:9 | remark:baby_test] 00CAF990
CData(int i,string &s)  [sequence:10 | remark:baby_test]        00CAF968
push CData to vector
max size of vector<CData> is 134217727
size of vector<CData> is 0
****************vec_data.push_back(data1)
CData(const CData &data)        [sequence:1 | remark:baby_test] 010485A8
****************vec_data.push_back(data2)
CData(const CData &data)        [sequence:1 | remark:baby_test] 01046F60
~CData()        010485A8
CData(const CData &data)        [sequence:2 | remark:baby_test] 01046F80
****************vec_data.push_back(data3)
CData(const CData &data)        [sequence:1 | remark:baby_test] 0104D230
CData(const CData &data)        [sequence:2 | remark:baby_test] 0104D250
~CData()        01046F60
~CData()        01046F80
CData(const CData &data)        [sequence:3 | remark:baby_test] 0104D270
****************vec_data.push_back(data4)
CData(const CData &data)        [sequence:1 | remark:baby_test] 0104D2C0
CData(const CData &data)        [sequence:2 | remark:baby_test] 0104D2E0
CData(const CData &data)        [sequence:3 | remark:baby_test] 0104D300
~CData()        0104D230
~CData()        0104D250
~CData()        0104D270
CData(const CData &data)        [sequence:4 | remark:baby_test] 0104D320
****************vec_data.push_back(data5)
CData(const CData &data)        [sequence:1 | remark:baby_test] 0104E430
CData(const CData &data)        [sequence:2 | remark:baby_test] 0104E450
CData(const CData &data)        [sequence:3 | remark:baby_test] 0104E470
CData(const CData &data)        [sequence:4 | remark:baby_test] 0104E490
~CData()        0104D2C0
~CData()        0104D2E0
~CData()        0104D300
~CData()        0104D320
CData(const CData &data)        [sequence:5 | remark:baby_test] 0104E4B0
****************vec_data.push_back(data6)
CData(const CData &data)        [sequence:6 | remark:baby_test] 0104E4D0
****************vec_data.push_back(data7)
CData(const CData &data)        [sequence:1 | remark:baby_test] 0104D230
CData(const CData &data)        [sequence:2 | remark:baby_test] 0104D250
CData(const CData &data)        [sequence:3 | remark:baby_test] 0104D270
CData(const CData &data)        [sequence:4 | remark:baby_test] 0104D290
CData(const CData &data)        [sequence:5 | remark:baby_test] 0104D2B0
CData(const CData &data)        [sequence:6 | remark:baby_test] 0104D2D0
~CData()        0104E430
~CData()        0104E450
~CData()        0104E470
~CData()        0104E490
~CData()        0104E4B0
~CData()        0104E4D0
CData(const CData &data)        [sequence:7 | remark:baby_test] 0104D2F0
****************vec_data.push_back(data8)
CData(const CData &data)        [sequence:8 | remark:baby_test] 0104D310
****************vec_data.push_back(data9)
CData(const CData &data)        [sequence:9 | remark:baby_test] 0104D330
****************vec_data.push_back(data10)
CData(const CData &data)        [sequence:1 | remark:baby_test] 0104ED28
CData(const CData &data)        [sequence:2 | remark:baby_test] 0104ED48
CData(const CData &data)        [sequence:3 | remark:baby_test] 0104ED68
CData(const CData &data)        [sequence:4 | remark:baby_test] 0104ED88
CData(const CData &data)        [sequence:5 | remark:baby_test] 0104EDA8
CData(const CData &data)        [sequence:6 | remark:baby_test] 0104EDC8
CData(const CData &data)        [sequence:7 | remark:baby_test] 0104EDE8
CData(const CData &data)        [sequence:8 | remark:baby_test] 0104EE08
CData(const CData &data)        [sequence:9 | remark:baby_test] 0104EE28
~CData()        0104D230
~CData()        0104D250
~CData()        0104D270
~CData()        0104D290
~CData()        0104D2B0
~CData()        0104D2D0
~CData()        0104D2F0
~CData()        0104D310
~CData()        0104D330
CData(const CData &data)        [sequence:10 | remark:baby_test]        0104EE48
===============show vector by iterator
address of itr is 0104ED28      value is [sequence:1 | remark:baby_test]
address of itr is 0104ED48      value is [sequence:2 | remark:baby_test]
address of itr is 0104ED68      value is [sequence:3 | remark:baby_test]
address of itr is 0104ED88      value is [sequence:4 | remark:baby_test]
address of itr is 0104EDA8      value is [sequence:5 | remark:baby_test]
address of itr is 0104EDC8      value is [sequence:6 | remark:baby_test]
address of itr is 0104EDE8      value is [sequence:7 | remark:baby_test]
address of itr is 0104EE08      value is [sequence:8 | remark:baby_test]
address of itr is 0104EE28      value is [sequence:9 | remark:baby_test]
address of itr is 0104EE48      value is [sequence:10 | remark:baby_test]
===============clear vector 1
~CData()        0104ED28
~CData()        0104ED48
~CData()        0104ED68
~CData()        0104ED88
~CData()        0104EDA8
~CData()        0104EDC8
~CData()        0104EDE8
~CData()        0104EE08
~CData()        0104EE28
~CData()        0104EE48
size of vector<CData> is 0
capacity of vector<CData> is 20
****************vec_data.push_back(data1)
CData(const CData &data)        [sequence:1 | remark:baby_test] 0104EEF8
****************vec_data.push_back(data2)
CData(const CData &data)        [sequence:2 | remark:baby_test] 0104EF18
****************vec_data.push_back(data3)
CData(const CData &data)        [sequence:3 | remark:baby_test] 0104EF38
****************vec_data.push_back(data4)
CData(const CData &data)        [sequence:4 | remark:baby_test] 0104EF58
****************vec_data.push_back(data5)
CData(const CData &data)        [sequence:5 | remark:baby_test] 0104EF78
****************vec_data.push_back(data6)
CData(const CData &data)        [sequence:6 | remark:baby_test] 0104EF98
****************vec_data.push_back(data7)
CData(const CData &data)        [sequence:7 | remark:baby_test] 0104EFB8
****************vec_data.push_back(data8)
CData(const CData &data)        [sequence:8 | remark:baby_test] 0104EFD8
****************vec_data.push_back(data9)
CData(const CData &data)        [sequence:9 | remark:baby_test] 0104EFF8
****************vec_data.push_back(data10)
CData(const CData &data)        [sequence:10 | remark:baby_test]        0104F018
===============show vector by iterator 2
address of itr is 0104EEF8      value is [sequence:1 | remark:baby_test]
address of itr is 0104EF18      value is [sequence:2 | remark:baby_test]
address of itr is 0104EF38      value is [sequence:3 | remark:baby_test]
address of itr is 0104EF58      value is [sequence:4 | remark:baby_test]
address of itr is 0104EF78      value is [sequence:5 | remark:baby_test]
address of itr is 0104EF98      value is [sequence:6 | remark:baby_test]
address of itr is 0104EFB8      value is [sequence:7 | remark:baby_test]
address of itr is 0104EFD8      value is [sequence:8 | remark:baby_test]
address of itr is 0104EFF8      value is [sequence:9 | remark:baby_test]
address of itr is 0104F018      value is [sequence:10 | remark:baby_test]
===============clear vector 2
~CData()        0104EEF8
~CData()        0104EF18
~CData()        0104EF38
~CData()        0104EF58
~CData()        0104EF78
~CData()        0104EF98
~CData()        0104EFB8
~CData()        0104EFD8
~CData()        0104EFF8
~CData()        0104F018
======================end of process
~CData()        00CAF968
~CData()        00CAF990
~CData()        00CAF9B8
~CData()        00CAF9E0
~CData()        00CAFA08
~CData()        00CAFA30
~CData()        00CAFA58
~CData()        00CAFA80
~CData()        00CAFAA8
~CData()        00CAFAD0

以上是关于vector的内存分配机制分析的主要内容,如果未能解决你的问题,请参考以下文章

map的内存分配机制分析

STL及一些容器底层实现机制

STL源码分析--vector

[转载]NGINX原理分析 之 SLAB分配机制

方法与对象内存分析

14.VisualVM使用详解15.VisualVM堆查看器使用的内存不足19.class文件--文件结构--魔数20.文件结构--常量池21.文件结构访问标志(2个字节)22.类加载机制概(代码片段