第六十九课 自定义内存管理
文章目录
一、统计对象中某个成员变量的访问次数
#include <iostream>
#include <string>
using namespace std;
class Test{
int value;
mutable int count;
public:
Test(int val)
{
value = val;
count = 0;
}
int getVal()
{
count ++;
return value;
}
void setVal(int val)
{
count ++;
value = val;
}
int getCount()
{
return count;
}
};
mutable 关键字
- mutable 是为了突破const 函数的限制而设计的
- mutable 成员变量将永远处于可改变的状态
- mutable 在实际项目开发中严禁滥用
mutable 的坏处
- mutable 成员变量破坏了只读对象的内部状态
- const 成员函数保证只读对象的状态不变性
- mutable 成员变量的出现无法保证状态不变性
解法2
#include <iostream>
#include <string>
using namespace std;
class Test{
int value;
int* const count;
public:
Test(int val):count(new(int(0)))
{
value = val;
count = 0;
}
int getVal()
{
*count = *count + 1;
return value;
}
void setVal(int val)
{
*count = *count + 1;
value = val;
}
int getCount()
{
return count;
}
};
二、new关键字创建出来的对象位于什么地方?
-
new/delete的本质是C++预定义的操作符
-
C++ 对这两个操作符做了严格的行为定义
new
- 获取足够大的内存空间(默认为堆空间)
- 在获取的空间中调用构造函数创建对象
delete
- 调用析构函数销毁对象
- 归还对象只能用的空间(默认为堆空间)
-
在C++中重载 new / delete 操作符
全局重载(不推荐)
局部重载(针对具体类进行重载)
重载的意义在于改变动态对象创建时的内存分配方式
-
重载方式(默认为静态成员函数)
void* operator new(unsigned int size) { void* ret = NULL; ... return ret; } void operator delete(void *p) { ... }
三、如何在指定的地址上创建 C++ 对象
-
解决方案:
在类中重载 new / delete 操作符
在 new 的操作符重载函数中返回指定的地址
在 delete 操作符中编辑对应的地址可用
答案:
通过重载可以在任意合法地址上创建 C++ 对象
四、new[] / delete[] 与 new / delete
-
new[] / delete[] 与 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 的本质为操作符
- 可以通过全局函数重载 new /delete (不推荐)
- 可以针对具体的类重载 new / delete
- new[] / delete[] 与new / delete 完全不同
- new[] / delete[] 也是可以被重载的操作符
- new[] 实际需要返回的内存空间可能比期望的要多