|
|
@@ -614,3 +614,107 @@ void Airplane::operator delete(void* p, size_t size)
|
|
|
|
|
|

|
|
|
|
|
|
+为了实现自己的内存分配,我们给 `Airplane` 和 `Screen` 两个类重写了 `operator new` 和 `operator delete`
|
|
|
+
|
|
|
+**那么如果我有100个类甚至1000个类又该如何?我们不能给每个类都重写** `operator new` **和** `operator delete` **吧?关键是每个类的写法相似,功能相同,所以得想一个办法把自定义内存分配的操作从对象中剥离出来**
|
|
|
+
|
|
|
+所以我们需要一个 `allocator` 分配器对象
|
|
|
+
|
|
|
+```cpp
|
|
|
+#include <cstddef>
|
|
|
+#include <iostream>
|
|
|
+
|
|
|
+class MyAllocator {
|
|
|
+private:
|
|
|
+ struct obj
|
|
|
+ {
|
|
|
+ struct obj* next;
|
|
|
+ };
|
|
|
+
|
|
|
+public:
|
|
|
+ void* allocate(size_t);
|
|
|
+ void deallocate(void*, size_t);
|
|
|
+
|
|
|
+private:
|
|
|
+ obj* freeStore = nullptr;
|
|
|
+ const int CHUNK = 5; // 标准库是20
|
|
|
+};
|
|
|
+
|
|
|
+void* MyAllocator::allocate(size_t size)
|
|
|
+{
|
|
|
+ obj* p = nullptr;
|
|
|
+ if (!freeStore) {
|
|
|
+ size_t chunk = CHUNK * size;
|
|
|
+ freeStore = p = (obj*)malloc(chunk);
|
|
|
+
|
|
|
+ if (p == nullptr) {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 连接内存块
|
|
|
+ for (int i = 0; i < CHUNK - 1; ++i) {
|
|
|
+ p->next = (obj*)((char*)p + size);
|
|
|
+ p = p->next;
|
|
|
+ }
|
|
|
+
|
|
|
+ p->next = nullptr; // last
|
|
|
+ }
|
|
|
+ p = freeStore;
|
|
|
+ freeStore = freeStore->next;
|
|
|
+ return p;
|
|
|
+}
|
|
|
+
|
|
|
+void MyAllocator::deallocate(void* p, size_t)
|
|
|
+{
|
|
|
+ // 将 p 收回插入 free list 前端
|
|
|
+ ((obj*)p)->next = freeStore;
|
|
|
+ freeStore = (obj*)p;
|
|
|
+}
|
|
|
+
|
|
|
+class Goo {
|
|
|
+public:
|
|
|
+ long L;
|
|
|
+ static MyAllocator myAlloc;
|
|
|
+
|
|
|
+public:
|
|
|
+ Goo(long l): L(l) {}
|
|
|
+ static void* operator new(size_t size) {
|
|
|
+ return myAlloc.allocate(size);
|
|
|
+ }
|
|
|
+
|
|
|
+ static void operator delete(void* pDead, size_t size) {
|
|
|
+ myAlloc.deallocate(pDead, size);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+MyAllocator Goo::myAlloc;
|
|
|
+
|
|
|
+void foo_myALlocator() {
|
|
|
+ std::cout << sizeof(Goo) << std::endl;
|
|
|
+
|
|
|
+ size_t const N = 4;
|
|
|
+ Goo* p[N];
|
|
|
+
|
|
|
+ for (int i = 0; i < N; ++i) {
|
|
|
+ p[i] = new Goo(i);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < 3; ++i) {
|
|
|
+ std::cout << p[i] << std::endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < N; ++i) {
|
|
|
+ delete p[i];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int main() {
|
|
|
+ foo_myALlocator();
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> 上面的代码可能运行不了(与编译器版本有关),但是可以表达我们对 allocator 运行的机制
|
|
|
+
|
|
|
+使用这种写法的 allocator 的内存分配器可以给其他任意类型的对象使用,对象无需再关注内存如何分配,而是仅仅需要引入 `MyAllocator` 并且在 `operator new` 和 `operator delete` 中使用即可
|
|
|
+
|