Есть ли способ синглтон класс оставить в стеке?

Рейтинг: -1Ответов: 3Опубликовано: 10.05.2023

Классическая реализация синглетоне такая(из банды четырёх):

Singleton (одиночка) (130) Гарантирует, что некоторый класс может иметь только один экземпляр, и предоставляет глобальную точку доступа к нему.

class Singleton {
public:
    static Singleton* Instance();
protected:
    Singleton();
private:
    static Singleton* _instance;
};

А реализация такова:

Singleton* Singleton::_instance = nullptr;
Singleton* Singleton::Instance () {
    if (_instance == nullptr) {
        _instance = new Singleton;
    }
    return _instance;
}

Тогда, любой класс, кто обвязан одиночкой, автоматом всегда лежит в куче. Что делать если хотелось бы его переместить в стек, при условии что его глобальность не нужна?

Ответы

▲ 1

Синглетон Александреску:

class Singleton {
public:
    static Singleton* Instance() {
       static  Singleton ret;
       return & ret;
    }
protected:
    Singleton();
};

Экземпляр лежит не на стеке, а в сегменте статических переменных. С точки зрения избегания new/delete, это тоже самое.

▲ 0

Скорее всего, раз не нужна "глоабльность", то нужен просто локальный static:

void func() {
    // Инициализация только при первом проходе
    static const auto singleton = Singleton::instance();
    // Либо
    static const Singleton singleton;
    // Но это не стековая переменная, а статическая область памяти.
    // Если нужно просто избежать выделения памяти в куче, то 
    // ответ уже был дан ранее.
}
▲ -1

Вы хотите что-то такое?

class Instance {
public:
    Instance()
    {
        if (global_instance_.expired()) {
            instance_ = std::make_shared<Singleton>();
            global_instance_ = instance_;
        } else {
            instance_ = global_instance_.lock();
        }
    }
private:
    class Singleton {

    };

    std::shared_ptr<Singleton> instance_;
    static std::weak_ptr<Singleton> global_instance_;
};

Или, что аналогично, просто возвращайте shared_ptr в Singleton::Instance().