Ответ
Чтобы запретить создание объекта в динамической памяти (куче) с помощью оператора new, нужно удалить (или сделать приватными) соответствующие операторы new.
Современный способ (C++11 и новее): = delete
class StackOnly {
public:
StackOnly() = default;
// Удаляем операторы new
void* operator new(std::size_t) = delete;
void* operator new[](std::size_t) = delete;
// Также можно удалить placement new для полноты
void* operator new(std::size_t, void*) = delete;
};
int main() {
StackOnly obj; // OK: объект на стеке
// StackOnly* p = new StackOnly(); // Ошибка: 'operator new' is deleted
// StackOnly* arr = new StackOnly[5]; // Ошибка: 'operator new[]' is deleted
return 0;
}
Устаревший способ (до C++11): приватные операторы new
class StackOnlyOld {
private:
void* operator new(std::size_t); // Не определяем
void* operator new[](std::size_t); // Не определяем
public:
StackOnlyOld() {}
};
Важные нюансы:
- Этот метод не препятствует созданию объекта в статической памяти (глобальные/статические переменные) или на стеке.
- Он не препятствует созданию объекта как члена другого класса, который сам создается в куче.
- Основная цель — предотвратить явное использование
newдля данного типа, что полезно для контроля над временем жизни объектов или для классов, управляющих критичными ресурсами.
Ответ 18+ 🔞
А, слушай, вот тебе история про то, как заставить объект сидеть на стеке и не высовываться. Представь себе класс — такой зазнайка, который говорит: «Я, блядь, слишком хорош для этой помойки под названием куча, создавай меня только на стеке, ёпта». И это реально можно устроить, если наглухо забанить операторы new.
Нормальный, современный способ (C++11 и дальше): просто удали их нахуй
class StackOnly {
public:
StackOnly() = default;
// Вот тут просто берём и вычёркиваем операторы new из жизни класса
void* operator new(std::size_t) = delete;
void* operator new[](std::size_t) = delete;
// Для полного параноидального счастья можно и placement new прибить
void* operator new(std::size_t, void*) = delete;
};
int main() {
StackOnly obj; // Окей, живёшь на стеке — молодец
// StackOnly* p = new StackOnly(); // Ошибка компиляции: оператор new удалён, иди нахуй
// StackOnly* arr = new StackOnly[5]; // Та же песня, нихуя не выйдет
return 0;
}
Старый дедовский способ (для мазохистов и легаси-кода): спрятать в приват
class StackOnlyOld {
private:
void* operator new(std::size_t); // Объявили приватным и даже не определяем — пусть линкер матерится
void* operator new[](std::size_t); // Тоже самое
public:
StackOnlyOld() {}
};
Но есть нюансы, ёб твою мать:
- Этот фокус не мешает создать объект как глобальную или статическую переменную. То есть он не строго стековый, он просто против кучи.
- Он не помешает, если этот объект будет полем другого класса, а тот уже создадут через
new. Получится, что наш красавец всё равно окажется в куче, но опосредованно — хитрая жопа. - Смысл всей этой движухи — жёсткий контроль. Например, для классов, которые работают с какими-нибудь ресурсами, которые нельзя копировать или которые должны умирать ровно тогда, когда вышли из scope. Чтобы какой-нибудь распиздяй не нагородил
newи не забылdelete. Будет вам хиросима и нагасаки, а потом удивление — пиздец, утечка.