类重载 new 和 delete vs 放置 new 与定制的内存类

Posted

技术标签:

【中文标题】类重载 new 和 delete vs 放置 new 与定制的内存类【英文标题】:class overloaded new and delete vs placement new with a bespoke memory class 【发布时间】:2013-04-18 02:43:42 【问题描述】:

我正在调查使用类重载新闻和删除与放置新闻之间的利弊。我的意思是,要么使用自己的运算符重载声明我可能希望新建和删除的每个类,要么使用内存管理器通过放置 new 为我提供所需的内存。

我有一个内存管理器,它允许我从多个池中分配内存:

enum MemPool

  kPool1,
  kPool2,


class MemoryManager

public:
  template <typename T>
  void* Allocate(MemPool pool); 
  void  Remove(MemPool pool, void* ptr);

;

MemoryManager g_mmgr;

分配是模板化的,因为在调试模式下我存储了每个分配的名称(通过 typeid(T).name()),我可以通过 sizeof(T) 获得每个分配的大小

我认为自己在如何分配方面至少有 2 个选项,并且正在尝试确定哪个在语法使用、效率、安全性和可移植性方面最好。

选项 1 是有一个带有新闻和删除的模板化基类,它封装了内存池并为我很好地键入。

template <typename T, MemPool pool>
class MemPoolUser

public:
  static void* operator new(int size)
  
    return g_mmgr.Allocate<T>(pool);
  

  static void operator delete(void* ptr)
  
    g_mmgr.Remove(pool,ptr);
  
;

然后我可以确保每个可能需要通过 MemoryManager 更新的类都这样声明:

class MyClass : public MemPoolUser<MyClass, kPool1>


;

这将使我能够简单地做

MyClass* c = new MyClass();
...
delete c;

会调用 MemPoolUser 中正确的 new 和 delete。

选项 2 是使用展示位置新闻:

class MyClass


;

MyClass* c = new (g_mmgr.Allocate<MyClass>(kPool1)) MyClass();
....
c->~MyClass();
g_mmgr.Remove(kPool1,c);

这些选项的优缺点?选项 1 看起来更简洁,但我必须知道我希望每个类从中分配的内存池类型,这可能取决于其他运行时因素。

选项 2 更灵活,但新增和删除在语法上很难看(它可以包含在 #defines 中)

所以我的问题是,除了上面提到的问题之外,这两个选项还有什么我没有考虑过的,并且一个比另一个更危险吗?

【问题讨论】:

我真正想尝试的是有一个模板化的全局 new 和 delete ,它将 mempool 作为一种类型以及正在更新的对象的类型,但即使我可以定义这些函数,它如果不显式调用运算符 new 就不可能调用它们,它不会调用 ctor 或 dtor 进行删除。 【参考方案1】:

如果你必须首先这样做(我希望你确实有一些相当不错的用例,其中对这些对象的特定内存池有一些特定的需求),我肯定会选择operator newoperator delete 解决方案。它允许您的应用程序代码在典型代码之外以最少的额外代码编写使用它。

【讨论】:

以上是关于类重载 new 和 delete vs 放置 new 与定制的内存类的主要内容,如果未能解决你的问题,请参考以下文章

类模板 友元重载形式 各种运算符重载 new delete ++ = +=

创建类时我应该在哪里放置new / delete

c++ primer19.1.1重载new和delete

C++学习32 重载new和delete运算符

我们可以重载malloc()吗?

问题是在具有-02或以上优化的框架中重载运算符new和delete [关闭]