C ++: общие мысли о перегрузке оператора new - PullRequest
2 голосов
/ 12 марта 2011

Вы перегружены operator new в C ++?

Если да, то почему?

Вопрос для интервью, для которого я смиренно прошу некоторые ваши мысли.

Ответы [ 6 ]

7 голосов
/ 12 марта 2011

У нас была встроенная система, в которой new было разрешено только в редких случаях, и память никогда не могла быть удалена, поскольку мы должны были доказать максимальное использование кучи из соображений надежности.

У нас была сторонняя библиотекаразработчик, которому не нравились эти правила, поэтому они перегружали new и delete, чтобы работать с частью памяти, которую мы выделили только для них.

4 голосов
/ 12 марта 2011

Да.

Оператор перегрузки new дает вам возможность контролировать, где объект находится в памяти. Я сделал это, потому что я знал некоторые подробности о времени жизни моих объектов и хотел избежать фрагментации на платформе, которая не имела виртуальной памяти.

2 голосов
/ 12 марта 2011

Да, по двум причинам: настраиваемый распределитель и отслеживание настраиваемого выделения.

2 голосов
/ 12 марта 2011

Вы бы перегрузили new, если вы используете свой собственный распределитель, делаете что-то необычное с подсчетом ссылок, инструментами для сбора мусора, отладкой времени жизни объектов или чем-то еще полностью;вы заменяете распределитель для объектов.Лично мне пришлось сделать это, чтобы определенные объекты были размещены на определенных страницах памяти mmap.

1 голос
/ 12 марта 2011

Перегрузка нового оператора может показаться хорошей идеей на первый взгляд, если вы хотите по каким-то причинам выполнить пользовательское выделение (т. Е. Избежать фрагментации памяти, присущей распределителю c-runtime или / и избежать блокировок вызовов управления памятью в многопоточных программах).Но когда вы переходите к реализации, вы можете понять, что в большинстве случаев вы хотите передать некоторый дополнительный контекст этому вызову, например, специфичную для потока кучу для объектов заданного размера.И перегрузка new / delete здесь просто не работает.Поэтому, в конце концов, вы можете захотеть создать свой собственный фасад для своей подсистемы управления памятью.

0 голосов
/ 15 апреля 2016

Мне было очень удобно перегружать operator new при написании кода расширения Python на C ++. Я поместил код Python C-API для распределения и освобождения в operator new и operator delete перегрузки соответственно - это позволяет PyObject* -совместимым структурам, которые могут быть созданы с new MyType() и управляться с предсказуемой семантикой выделения кучи.

Он также позволяет разделить код выделения (обычно в методе Python __new__) и код инициализации (в __init__ Python) соответственно на перегрузки 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;
        }
    }

    /* … */

};
...