C++ 第69-02篇 技巧:自定义内存管理

“ 这牛究竟有多少名字? ”
“ 这牛叫福贵,就一个名字。 ”

面试题

new 关键字创建出来的对象位于什么地方?

被忽略的事实一

new / delete 的本质是C++ 预定义的操作符
C++ 对这两个操作符做出了严格行为定义
new:
	获取足够大的内存空间(默认为堆空间)
	在获取的空间中调用构造函数创建对象
delete:
	调用析构函数销毁对象
	归还对象所占用的空间(默认为堆空间)

被忽略的事实二

在C++中能够重载 new / delete 操作符
全局重载 ( 不推荐 )
局部重载( 针对具体类型进行重载 )
注: 重载 new / delete 的意义在于改变动态对象创建时的内存分配方式

new / delete 的重载方式

//  static member function
void* operator new (unsigned int size)  // 参数代表需要获得内存大小
{
	void* ret = NULL;
	/* ret point to allocated memory*/
	return ret; 
}

//  static member function
void operator delete (void* p)  // 参数指针指向对应对象的地址(要释放的地址)
{
	/* free the memory which is pointed by p*/
}

// 这两个类默认为静态成员函数

编程试验:

静态存储区中创建动态对象



#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:
	void* operator new (unsigned int size)  
	{
		void* ret = NULL;
		
		for(int i=0; i<COUNT; i++)  // 通过循环查找buffer中空闲位置,用于创建 Test 对象
        {
            if( !c_map[i] )         // 如果没被标记(没有对象存在)
            {
                c_map[i] = 1;
                
                ret = c_buffer + i * sizeof(Test); //查找 c_buffer 可用空间的首地址
                
                cout << "succeed to allocate memory: " << ret << endl;
                
                break;
            }
        }
	
		return ret; 
	}


	void operator delete (void* p)  
	{
		if( p != NULL )
        {
            char* mem = reinterpret_cast<char*>(p);
            int index = (mem - c_buffer) / sizeof(Test);  // 指针的减法运算,得到:要释放的动态对象在c_map[]标记数组中的位置
            int flag = (mem - c_buffer) % sizeof(Test);   // 这些位置必须是固定的,如果flag不为0,那么指针不合法;
            
            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};  // 静态数组在类外分配空间, 定义静态内存空间,存储Test对象,最多存储4个
char Test::c_map[Test::COUNT] = {0};                    // 标记数组,用来标记在哪里已经创建了对象


int main(int argc, char *argv[])
{
	// 验证1
 	cout << "===== Test Single Object =====" << endl;
	Test* pt = new Test;
	delete pt;
	cout << "===== Test Object Array =====" << endl;
	
	
	// 验证2
	Test* pa[5] = {0};
	
    for(int i=0; i<5; i++)  // 动态创建5个对象  最后一个为0
    {
        pa[i] = new Test;
        
        cout << "pa[" << i << "] = " << pa[i] << endl;
    }
    
    for(int i=0; i<5; i++)
    {
        cout << "delete " << pa[i] << endl;
        
        delete pa[i];
    }

	return 0;
}

// 可以和二节构造相结合,固定产生多少个对象---> N 例模式


感谢关注,文章持续高速更新中······

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页