自定义内存管理
问题一:统计对象中某个成员变量的访问次数(访问次数包括读的次数和写的次数)
-
遗失的关键字
-
mutable是为了突破const函数的限制而设计的
-
mutable成员变量将永远处于可改变的状态
-
mutable在实际的项目开发中被严禁滥用
-
mutable成员变量破坏了只读对象的内部状态
-
const成员函数保证只读对象的状态不变性
-
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++对这两个操作符做了严格的行为定义
-
new:获取足够大的内存空间(默认为堆空间),在获取的空间中调用构造函数创建对象。
-
delete:调用析构函数销毁对象,归还对象所占用的空间(默认为堆空间)。
-
在C++中能够重载new/delete操作符
-
全局重载(不推荐)
-
局部重载(针对具体类进行重载)
-
重载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++对象?
-
解决方案
-
在类中重载new/delete操作符
-
在new的操作符重载函数中返回指定的地址
-
在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[]能够被重载,进而改变内存管理方式
-
new[]/delete[]的重载方式
void* operator new[] (unsigned int size) { return malloc(size); } void operator delete[] (void*p) { free(p); }
-
注意事项
-
new[]实际需要返回的内存空间可能比期望的要多
-
对象数组占用的内存中需要保存数组信息
-
数组信息用于确认构造函数和析构函数的调用次数
// 重载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; }
-
运行结果
主要记录的是学习听课的笔记