【问题标题】:C++: general thoughts about overloading operator newC++:关于重载 operator new 的一般想法
【发布时间】:2011-07-13 19:59:56
【问题描述】:

您是否在 C++ 中重载了 operator new

如果是,为什么?

一个面试问题,我谦虚地请求你的一些想法。

【问题讨论】:

  • “否”是最简单的正确答案。
  • @SP:虽然一般情况下最好避免这样做,但正如其他答案所解释的那样,有一些合理的情况。
  • @Matteo Italia 这仍然是一个正确的答案,因为问题是问 you 是否曾经重载过新的运算符。

标签: c++ memory-management operator-overloading new-operator


【解决方案1】:

我们有一个嵌入式系统,其中 new 很少被允许,并且内存永远不会被删除,因为出于可靠性原因,我们必须证明最大堆使用量。

我们有一个第三方库开发人员不喜欢这些规则,因此他们重载了 newdelete 来处理我们仅为他们分配的一块内存。

【讨论】:

    【解决方案2】:

    是的。

    重载 operator new 使您有机会控制对象在内存中的位置。我这样做是因为我知道有关对象生命周期的一些细节,并且希望避免在没有虚拟内存的平台上产生碎片。

    【讨论】:

      【解决方案3】:

      如果您使用自己的分配器、在引用计数方面做一些花哨的事情、为垃圾收集检测、调试对象生命周期或完全其他事情,您将重载 new;您正在替换对象的分配器。我个人不得不这样做以确保某些对象被分配到特定的 mmap 内存页上。

      【讨论】:

        【解决方案4】:

        是的,有两个原因:自定义分配器和自定义分配跟踪。

        【讨论】:

          【解决方案5】:

          如果您出于某种原因想要进行自定义分配(即避免 c-runtime 分配器固有的内存碎片或/和避免多线程程序中的内存管理调用锁定),重载 new 运算符乍一看可能是一个好主意。但是当您开始实现时,您可能会意识到,在大多数情况下,您希望将一些额外的上下文传递给此调用,例如给定大小的对象的线程特定堆。重载 new/delete 在这里根本行不通。因此,最终您可能希望为自定义内存管理子系统创建自己的外观。

          【讨论】:

            【解决方案6】:

            在用 C++ 编写 Python 扩展代码时,我发现重载 operator new 非常方便。我将用于分配和释放的 Python C-API 代码分别包装在 operator newoperator delete 重载中——这允许 PyObject* 兼容的结构可以使用 new MyType() 创建并使用可预测的堆分配语义进行管理。

            它还允许将分配代码(通常在 Python __new__ 方法中)和初始化代码(在 Python 的 __init__ 中)分别分离到 operator new 重载和任何我们认为适合的构造函数中定义。

            这是一个示例:

            struct ModelObject {
            
                static PyTypeObject* type_ptr() { return &ModelObject_Type; }
            
                /// operator new performs the role of tp_alloc / __new__
                /// Not using the 'new size' value here
                void* operator new(std::size_t) {
                    PyTypeObject* type = type_ptr();
                    ModelObject* self = reinterpret_cast<ModelObject*>(
                        type->tp_alloc(type, 0));
                    if (self != NULL) {
                        self->weakrefs = NULL;
                        self->internal = std::make_unique<buffer_t>(nullptr);
                    }
                    return reinterpret_cast<void*>(self);
                }
            
                /// operator delete acts as our tp_dealloc
                void operator delete(void* voidself) {
                    ModelObject* self = reinterpret_cast<ModelObject*>(voidself);
                    PyObject* pyself = reinterpret_cast<PyObject*>(voidself);
                    if (self->weakrefs != NULL) { PyObject_ClearWeakRefs(pyself); }
                    self->cleanup();
                    type_ptr()->tp_free(pyself);
                }
            
                /// Data members
                PyObject_HEAD
                PyObject* weakrefs = nullptr;
                bool clean = false;
                std::unique_ptr<buffer_t> internal;
            
                /// Constructors fill in data members, analagous to __init__
                ModelObject()
                    :internal(std::make_unique<buffer_t>())
                    ,accessor{}
                    {}
            
                explicit ModelObject(buffer_t* buffer)
                    :clean(true)
                    ,internal(std::make_unique<buffer_t>(buffer))
                    {}
            
                ModelObject(ModelObject const& other)
                    :internal(im::buffer::heapcopy(other.internal.get()))
                    {}
            
                /// No virtual methods are defined to keep the struct as a POD
                /// ... instead of using destructors I defined a 'cleanup()' method:
                void cleanup(bool force = false) {
                    if (clean && !force) {
                        internal.release();
                    } else {
                        internal.reset(nullptr);
                        clean = !force;
                    }
                }
            
                /* … */
            
            };
            

            【讨论】:

              猜你喜欢
              • 2019-04-10
              • 1970-01-01
              • 1970-01-01
              • 2021-07-28
              • 2012-01-03
              • 2021-10-11
              • 2011-01-22
              • 2012-01-30
              • 1970-01-01
              相关资源
              最近更新 更多