自定义内存管理

问题一:统计对象中某个成员变量的访问次数(访问次数包括读的次数和写的次数)
  • 遗失的关键字
  1. mutable是为了突破const函数的限制而设计的
  2. mutable成员变量将永远处于可改变的状态
  3. mutable在实际的项目开发中被严禁滥用
  4. mutable成员变量破坏了只读对象的内部状态
  5. const成员函数保证只读对象的状态不变性
  6. mutable成员变量的出现无法保证状态不变性
  • 是否有更好的解决方法?(可以得满分的代码)
#include <iostream>
#include <string>
using namespace std;
class Test
{
     int m_value;
     //地址在初始化后就不能变了
     int* const m_pcount;
public:
    Test(int value = 0):m_pcount(new int(0))
    {
        m_value = value;
    }
    //const成员函数不能直接修改成员变量的值
    int get_value() const
    {
       *m_pcount =*m_pcount+1 ;
        return m_value;
    }
    void set_value(int value)
    {
        *m_pcount = *m_pcount + 1;
        m_value = value;
    }
    int get_count() const
    {
        return *m_pcount;
    }
};
int main()
{
    Test T(10);
    T.set_value(100);
    cout << "T.m_value = " << T.get_value() << endl;
    cout << "T.m_count = " << T.get_count() << endl;
    const Test ct(200);
    cout << "ct.m_value = " << ct.get_value() << endl;
    cout << "ct.m_count = " << ct.get_count() << endl;
}
问题二:new关键字创建出来的对象位于什么地方?
  • new/delete的本质是C++预定义的操作符
  • C++对这两个操作符做了严格的行为定义
  1. new:获取足够大的内存空间(默认为堆空间),在获取的空间中调用构造函数创建对象。
  2. delete:调用析构函数销毁对象,归还对象所占用的空间(默认为堆空间)。
  • 在C++中能够重载new/delete操作符
  1. 全局重载(不推荐)
  2. 局部重载(针对具体类进行重载)
  3. 重载new/delete的意义在于改变动态创建时的内存分配方式
void* operator new(unsigned int size)
{
    void* ret = NULL;
    return ret;
}
void operator delete(void*p)
{
 
}
 
重载new/delete关键字,使其动态内存分配在静态存储区。(还可以达成一种效果:最多可以创建多少个对象)
// 重载new,delete关键字.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
class Test
{
    static const unsigned int count = 4;
    //静态存储区
    static char c_buffer[];
    static char c_map[];
    int m_value;
public:
    Test(int value=0)
    {
        m_value = value;
    }
    void* operator new(unsigned int size)
    {
        void* ret = NULL;
        for (int i =0;i<count;i++)
        {
            if (!c_map[i])
            {
                c_map[i] = 1;
                ret = c_buffer + i * sizeof(Test);
                cout << "succeed to acclcate memory:" << ret << endl;
                break;
            }
        }
        return ret;
    }
    void operator delete(void* p)
    {
        if (p!=NULL)
        {
            char* mem = reinterpret_cast<char*>(p);
            char index = (mem - c_buffer) / sizeof(Test);
            int flag = (mem - c_buffer) % sizeof(Test);
            if ((flag==0)&&(0 <= index)&&(index < count))
            {
                c_map[index] = 0;
                cout << "succeed to free memory:" << p << endl;
            }
        }
    }
};
char Test::c_buffer[sizeof(Test) * Test::count] = {0};
char Test::c_map[count] = {0};
int main()
{
    Test* pt = new Test;
    delete pt;
}
运行结果
succeed to acclcate memory:0014C2D0
succeed to free memory:0014C2D0
问题三:如何在指定的地址上创建C++对象?
  • 解决方案
  1. 在类中重载new/delete操作符
  2. 在new的操作符重载函数中返回指定的地址
  3. 在delete操作符重载中标记对应的地址可用
  • #include <iostream>
    #include <string>
    #include <cstdlib>
    using namespace std;
    class Test
    {
        static unsigned int c_count;
        //静态存储区
        static char* c_buffer;
        static char* c_map;
        int m_value;
    public:
        static bool SetMemory(char*memory,unsigned int size)
        {
            bool ret = false;
            c_count = size / sizeof(Test);
            ret = (c_count && (c_map =  reinterpret_cast<char*>(calloc(c_count,sizeof(char)))));
            if (ret)
            {
                c_buffer = memory;
            }
            else
            {
                free(c_map);
                c_map = NULL;
                c_buffer = NULL;
                c_count = 0;
            }
            return ret;
        }
        Test(int value = 0)
        {
            m_value = value;
        }
        void* operator new(unsigned int size)
        {
            void* ret = NULL;
            if (c_count>0)
            {
                for (int i = 0; i < c_count; i++)
                {
                    if (!c_map[i])
                    {
                        c_map[i] = 1;
                        ret = c_buffer + i * sizeof(Test);
                        cout << "succeed to acclcate memory:" << ret << endl;
                        break;
                    }
                }
            }
            else
            {
                ret = malloc(size);
            }
            return ret;
        }
        void operator delete(void* p)
        {
            if (p != NULL)
            {
                if (c_count>0)
                {
                    char* mem = reinterpret_cast<char*>(p);
                    char index = (mem - c_buffer) / sizeof(Test);
                    int flag = (mem - c_buffer) % sizeof(Test);
                    if ((flag == 0) && (0 <= index) && (index < c_count))
                    {
                        c_map[index] = 0;
                        cout << "succeed to free memory:" << p << endl;
                    }
                }
                else
                {
                    free(p);
                }
            }
        }
    };
    char* Test::c_buffer = NULL;
    char* Test::c_map = NULL;
    unsigned int Test::c_count = 0;
    int main()
    {
        //在栈上创建对象
        char buffer[12] = { 0 };
        Test::SetMemory(buffer,sizeof(buffer));
        Test* pt = new Test;
        delete pt;
    }
    new[]/delete[]与new/delete完全不同
  1. 动态对象数组创建通过new[]完成
  2. 动态对象数组的销毁通过delete[]完成
  3. new[]/delete[]能够被重载,进而改变内存管理方式
  • new[]/delete[]的重载方式
void* operator new[] (unsigned int size)
{
    return malloc(size);
}
void operator delete[] (void*p)
{
    free(p);
}
  • 注意事项
  1. new[]实际需要返回的内存空间可能比期望的要多
  2. 对象数组占用的内存中需要保存数组信息
  3. 数组信息用于确认构造函数和析构函数的调用次数
// 重载new[],delete[]操作符,进行动态内存管理.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Test
{
    int m_value;
public:
    Test():m_value(0)
    {
       
    }
    ~Test()
    {
    }
    void print()
    {
        cout << "hello" << endl;
    }
    void* operator new (unsigned int size)
    {
        cout << "operator new:" << size << endl;
        return malloc(size);
    }
    void operator delete(void* p)
    {
        cout << "operator delete:" << p << endl;
        free(p);
    }
    void* operator new[] (unsigned int size)
    {
        cout << "operator new[]:" << size << endl;
        return malloc(size);
    }
    void operator delete[] (void* p)
    {
        cout << "operator delete[]:" << p << endl;
        free(p);
    }
};
int main()
{
    Test* pt = NULL;
    pt = new Test;
    pt->print();
    delete pt;
    pt = new Test[5];
    pt[5].print();
    delete[] pt;
    
}
  • 运行结果
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2020-02-15 10:12  认真做个普通人  阅读(279)  评论(0编辑  收藏  举报