该程序演示了list在内存分配时候的问题。里面的备注信息是我的想法。
/* 功能说明: list的内存分配机制分析。 代码说明: list所管理的内存地址可以是不连续的。程序在不断的push_back的过程中,程序仅会将操作的元素进行复制一份,保存到list中。通过复制构造函数和析构函数,可以看到这些操作。 实现方式: 限制条件或者存在的问题: 无 */ #include <iostream> #include <string> #include <list> #include <windows.h> using namespace std; class CData { public: CData() { sequence = 0; this->remark = "default string"; cout << "CData() " << toString() << " " << this << endl; } CData(int i, string &s) { this->sequence = i; this->remark = s; cout << "CData(int i,string &s) " << toString() << " " << this << endl; } CData(const CData &data) { this->sequence = data.sequence; this->remark = data.remark; cout << "CData(const CData &data) " << toString() << " " << this << endl; } CData operator = (const CData &data) { this->sequence = data.sequence; this->remark = data.remark; cout << "CData operator = (const CData &data) " << toString() << " " << this << endl; return *this; } void setSequence(const int i) { this->sequence = i; } void setRemark(const string &s) { this->remark = s; } string toString() const { char tmp[2048] = { 0 }; sprintf(tmp, "[sequence:%d | remark:%s]", this->sequence, this->remark.c_str()); //此处应该有内存复制操作,所以不用担心返回后tmp数组所指向的内存被修改或者不存在的情况。 return tmp; } ~CData() { cout << "~CData() " << this << endl; } protected: private: int sequence; string remark; }; int main(int argc, char **argv) { cout << "process begin at " << (void*)&main << endl; string str = "baby_test"; CData data1(1, str); CData data2(2, str); CData data3(3, str); CData data4(4, str); CData data5(5, str); CData data6(6, str); CData data7(7, str); CData data8(8, str); CData data9(9, str); CData data10(10, str); cout << "push CData to list" << endl; list<CData> lst_data; cout << "max size of list<CData> is " << lst_data.max_size() << endl; cout << "size of list<CData> is " << lst_data.size() << endl; cout << "****************lst_data.push_back(data1)" << endl; lst_data.push_back(data1); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data2)" << endl; lst_data.push_back(data2); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data3)" << endl; lst_data.push_back(data3); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data4)" << endl; lst_data.push_back(data4); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data5)" << endl; lst_data.push_back(data5); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data6)" << endl; lst_data.push_back(data6); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data7)" << endl; lst_data.push_back(data7); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data8)" << endl; lst_data.push_back(data8); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data9)" << endl; lst_data.push_back(data9); Sleep(2 * lst_data.size()); cout << "****************lst_data.push_back(data10)" << endl; lst_data.push_back(data10); Sleep(2 * lst_data.size()); // 程序到此为止,可以看到在每次push的时候,对象的复制构造函数会调用一次。 cout << "===============show list by iterator" << endl; for (list<CData>::iterator itr = lst_data.begin(); itr != lst_data.end(); itr++) { // 显示的地址信息,是每次push的时候所复制的对象的地址。 cout << "address of itr is " << &(*itr) << " value is " << itr->toString() << endl; } cout << "===============clear list 1" << endl; // list中的元素不是指针,此处的清理,会调用析构函数。 lst_data.clear(); cout << "======================end of process" << endl; return 0; }
程序的结果:
process begin at 00B01749
CData(int i,string &s) [sequence:1 | remark:baby_test] 010FFCF8
CData(int i,string &s) [sequence:2 | remark:baby_test] 010FFCD0
CData(int i,string &s) [sequence:3 | remark:baby_test] 010FFCA8
CData(int i,string &s) [sequence:4 | remark:baby_test] 010FFC80
CData(int i,string &s) [sequence:5 | remark:baby_test] 010FFC58
CData(int i,string &s) [sequence:6 | remark:baby_test] 010FFC30
CData(int i,string &s) [sequence:7 | remark:baby_test] 010FFC08
CData(int i,string &s) [sequence:8 | remark:baby_test] 010FFBE0
CData(int i,string &s) [sequence:9 | remark:baby_test] 010FFBB8
CData(int i,string &s) [sequence:10 | remark:baby_test] 010FFB90
push CData to list
max size of list<CData> is 107374182
size of list<CData> is 0
****************lst_data.push_back(data1)
CData(const CData &data) [sequence:1 | remark:baby_test] 01176A58
****************lst_data.push_back(data2)
CData(const CData &data) [sequence:2 | remark:baby_test] 0117C7E8
****************lst_data.push_back(data3)
CData(const CData &data) [sequence:3 | remark:baby_test] 0117C840
****************lst_data.push_back(data4)
CData(const CData &data) [sequence:4 | remark:baby_test] 0117DE90
****************lst_data.push_back(data5)
CData(const CData &data) [sequence:5 | remark:baby_test] 0117DEE8
****************lst_data.push_back(data6)
CData(const CData &data) [sequence:6 | remark:baby_test] 0117DF40
****************lst_data.push_back(data7)
CData(const CData &data) [sequence:7 | remark:baby_test] 0117E018
****************lst_data.push_back(data8)
CData(const CData &data) [sequence:8 | remark:baby_test] 0117E1D0
****************lst_data.push_back(data9)
CData(const CData &data) [sequence:9 | remark:baby_test] 0117E598
****************lst_data.push_back(data10)
CData(const CData &data) [sequence:10 | remark:baby_test] 0117E540
===============show list by iterator
address of itr is 01176A58 value is [sequence:1 | remark:baby_test]
address of itr is 0117C7E8 value is [sequence:2 | remark:baby_test]
address of itr is 0117C840 value is [sequence:3 | remark:baby_test]
address of itr is 0117DE90 value is [sequence:4 | remark:baby_test]
address of itr is 0117DEE8 value is [sequence:5 | remark:baby_test]
address of itr is 0117DF40 value is [sequence:6 | remark:baby_test]
address of itr is 0117E018 value is [sequence:7 | remark:baby_test]
address of itr is 0117E1D0 value is [sequence:8 | remark:baby_test]
address of itr is 0117E598 value is [sequence:9 | remark:baby_test]
address of itr is 0117E540 value is [sequence:10 | remark:baby_test]
===============clear list 1
~CData() 01176A58
~CData() 0117C7E8
~CData() 0117C840
~CData() 0117DE90
~CData() 0117DEE8
~CData() 0117DF40
~CData() 0117E018
~CData() 0117E1D0
~CData() 0117E598
~CData() 0117E540
======================end of process
~CData() 010FFB90
~CData() 010FFBB8
~CData() 010FFBE0
~CData() 010FFC08
~CData() 010FFC30
~CData() 010FFC58
~CData() 010FFC80
~CData() 010FFCA8
~CData() 010FFCD0
~CData() 010FFCF8