Как предотвратить присвоение класса с помощью оператора "new"? (Я хотел бы убедиться, что мой класс RAII всегда размещен в стеке.)

Я хотел бы убедиться, что мой класс RAII всегда размещается в стеке.

Как предотвратить присвоение класса с помощью оператора "new"?

4 ответа

Все, что вам нужно сделать, это объявить новый оператор класса private:

class X
{
    private: 
      // Prevent heap allocation
      void * operator new   (size_t);
      void * operator new[] (size_t);
      void   operator delete   (void *);
      void   operator delete[] (void*);

    // ...
    // The rest of the implementation for X
    // ...
};  

Создание приватного "оператора new" эффективно предотвращает использование кода за пределами класса "new" для создания экземпляра X.

Для завершения вы должны скрыть "оператор удаления" и версии обоих операторов в массиве.

Начиная с C++11 вы также можете явно удалить функции:

class X
{
// public, protected, private ... does not matter
    static void *operator new     (size_t) = delete;
    static void *operator new[]   (size_t) = delete;
    static void  operator delete  (void*)  = delete;
    static void  operator delete[](void*)  = delete;
};

Смежный вопрос: возможно ли предотвратить выделение стека для объекта и разрешить его запуск только с помощью "new"?

Я не убежден в твоей мотивации.

Есть веские причины создавать классы RAII в бесплатном магазине.

Например, у меня есть класс блокировки RAII. У меня есть путь через код, где блокировка необходима только при соблюдении определенных условий (это проигрыватель видео, и мне нужно удерживать блокировку только во время цикла рендеринга, если у меня загружено и воспроизводится видео; если ничего не загружено, Мне это не нужно) Поэтому возможность создавать блокировки в бесплатном хранилище (с помощью scoped_ptr / auto_ptr) очень полезна; это позволяет мне использовать один и тот же путь кода независимо от того, должен ли я снять блокировку.

т.е. как то так:

auto_ptr<lock> l;
if(needs_lock)
{
    l.reset(new lock(mtx));
}
render();

Если бы я только мог создать блокировки в стеке, я бы не смог этого сделать....

@DrPizza:

Это интересный момент у вас есть. Обратите внимание, что в некоторых ситуациях идиома RAII не обязательно является необязательной.

В любом случае, возможно, лучший способ подойти к вашей дилемме - добавить параметр в конструктор блокировки, который указывает, нужна ли блокировка. Например:

class optional_lock
{
    mutex& m;
    bool dolock;

public:
    optional_lock(mutex& m_, bool dolock_)
        : m(m_)
        , dolock(dolock_)
    {
        if (dolock) m.lock();
    }
    ~optional_lock()
    {
        if (dolock) m.unlock();
    }
};

Тогда вы могли бы написать:

optional_lock l(mtx, needs_lock);
render(); 

В моей конкретной ситуации, если блокировка не нужна, мьютекс даже не существует, поэтому я думаю, что такой подход будет сложнее приспособить.

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

Другие вопросы по тегам