TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #1059 4.47K
​​Как запретить объекту создаваться на стеке? Классика
#новичкам

Вопрос относится скорее к категории "из собеседований", но новичкам все равно полезно задавать себе такие вопросы, чтобы проверить глубину понимания С++.

Можно удалить все конструкторы с помощью пометки delete и тогда объект вообще нигде нельзя будет создавать. Но вопрос скорее всего про другое: как запретить объекту создаваться на стеке, но не на куче или статической памяти?

Очевидно, что-то надо колдовать с конструкторами, потому что именно они создают объект.

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

Если мы хотим создавать объект только на куче можно написать так:

class MyClass {
private:
MyClass() { std::cout << "MyClass created\n"; }
public:
~MyClass() { std::cout << "MyClass destroyed\n"; }
static std::unique_ptr<MyClass> create() {
return std::unique_ptr<MyClass>(new MyClass());
}
void hello() const {
std::cout << "Hello, MyClass!\n";
}
};

auto obj = MyClass::create();
obj->hello();


Здесь фабричный метод создает std::unique_ptr, который и будет хранить указатель на класс. std::make_unique нельзя использовать, потому что внутри нее мы не сможем вызвать приватный конструктор.

Можно также удалить операции копирования и перемещения, потому что скорее всего в таком виде логика операций с MyClass не подразумевает копирования и перемещения.

Такой подход может быть полезен, если:

👉🏿 размер объекта очень большой и просто не влезет в стек

👉🏿 хотите реализовать всякие паттерны, типа object pool или оопшной фабрики.

👉🏿 нужно обрабатывать ошибки создания объекта без исключений - в случае ошибки просто вернем nullptr.

👉🏿 вы хотите какой-то особый контроль времени жизни.

Мы также можем разрешить создавать объект только в глобальной области. Такой паттерн называется синглтон:

class Singleton {
public:
static Singleton& instance() {
static Singleton inst;
return inst;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&&) = delete;
void foo() {}
private:
Singleton() = default;
~Singleton() = default;
};


Конструктор и деструктор приватные, копирование и перемещение вообще запрещены. И есть статический метод, который возвращает ссылку на инстанс класса. За счет того, что используется статическая локальная переменная inst, инициализация объекта гарантировано потокобезопасна(только один поток в итоге создаст объект). В этом воплощении паттерн получил название синглтон Майерса.

Синглтоны могут быть полезны, например, при реализации пула соединений, логгера или сборщика метрик.

Обсудили по сути самые классические практически применимые способы. В следующем посте будет уже экзотика. Если знаете какие-то необычные способы - пишите в комментах, разберем их в следующий раз.

Limit wrong uses. Stay cool.

#design #cppcore
  • ❤ 24
  • 👍 14
  • 🔥 7
More from @grokaemcpp
  1. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  2. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  3. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  4. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  5. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
  6. Sep 25, 2026​​std::spanstream #опытным Радостная весть для всех, кто пользуется iostreams! В C++23 доб…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →