Как предотвратить присвоение класса с помощью оператора "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();
В моей конкретной ситуации, если блокировка не нужна, мьютекс даже не существует, поэтому я думаю, что такой подход будет сложнее приспособить.
Я думаю, что я действительно изо всех сил пытаюсь понять, это оправдание для запрета создания этих объектов в бесплатном магазине.