Я бы хотел, чтобы мой класс RAII всегда был выделен в стеке.
Как предотвратить выделение класса с помощью "нового" оператора?
Я бы хотел, чтобы мой класс RAII всегда был выделен в стеке.
Как предотвратить выделение класса с помощью "нового" оператора?
Все, что вам нужно сделать, это объявить класс новым оператором 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
// ...
};
Создание "operator new" private эффективно предотвращает использование кода за пределами класса "new" для создания экземпляра X.
Чтобы выполнить все, вы должны скрыть "оператор delete" и версии массива обоих операторов.
С С++ 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;
};
Связанный с этим вопрос: Возможно ли предотвратить размещение стека в стеке и разрешить его только с помощью нового? p >
Я не убежден в вашей мотивации.
Есть веские причины для создания классов 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();
В моей конкретной ситуации, если блокировка не нужна, мьютекс вообще не существует, поэтому я думаю, что подход будет гораздо сложнее.
Я думаю, что я действительно пытаюсь понять, это оправдание запрета на создание этих объектов в свободном хранилище.