list的内存分配机制分析

Posted 聚沙成塔

tags:

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

该程序演示了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()\t" << toString() << "\t" << this << endl;
    }

    CData(int i, string &s)
    {
        this->sequence = i;
        this->remark = s;

        cout << "CData(int i,string &s)\t" << toString() << "\t" << this << endl;
    }

    CData(const CData &data)
    {
        this->sequence = data.sequence;
        this->remark = data.remark;

        cout << "CData(const CData &data)\t" << toString() << "\t" << this << endl;
    }

    CData operator = (const CData &data)
    {
        this->sequence = data.sequence;
        this->remark = data.remark;

        cout << "CData operator = (const CData &data)\t" << toString() << "\t" << 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()\t" << 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) << "\tvalue 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

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

map的内存分配机制分析

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

方法与对象内存分析

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

好未来源码分析:Golang内存分配

Chrome 浏览器垃圾回收机制与内存泄漏分析(未完成)