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 }
程序的结果:
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的内存分配机制分析的主要内容,如果未能解决你的问题,请参考以下文章
14.VisualVM使用详解15.VisualVM堆查看器使用的内存不足19.class文件--文件结构--魔数20.文件结构--常量池21.文件结构访问标志(2个字节)22.类加载机制概(代码片段