Sök…


Anmärkningar

En Singleton är utformad för att säkerställa att en klass endast har en instans och ger en global tillgång till den. Om du bara behöver en instans eller en bekväm global åtkomstpunkt, men inte båda, bör du överväga andra alternativ innan du vänder dig till singleton.

Globala variabler kan göra det svårare att resonera om kod. Om till exempel en av samtalsfunktionerna inte är nöjda med de data som den får från en Singleton måste du nu spåra vad som först ger singleton dåliga data i första hand.

Singletons uppmuntrar också till koppling , en term som används för att beskriva två kodkomponenter som är sammanfogade och därmed minska varje komponents eget mått på självinneslutning.

Singletons är inte samtidigt vänliga. När en klass har en global tillgångspunkt har varje tråd möjlighet att komma åt den vilket kan leda till dödlås och rasförhållanden.

Slutligen kan lat initiering orsaka prestandaproblem om de initialiseras vid fel tid. Att ta bort lata initialisering tar också bort några av de funktioner som gör Singleton intressant i första hand, till exempel polymorfism (se underklasser).

Källor: Spelprogrammeringsmönster av Robert Nyström

Latinitialisering

Det här exemplet har tagits bort från Q & A avsnittet här: http://stackoverflow.com/a/1008289/3807729

Se denna artikel för en enkel design för en lat utvärderad med garanterad förstörelse singleton:
Kan någon ge mig ett exempel på Singleton i c ++?

Den klassiska lata utvärderade och förstörde singleton korrekt.

class S
{
    public:
        static S& getInstance()
        {
            static S    instance; // Guaranteed to be destroyed.
                                  // Instantiated on first use.
            return instance;
        }
    private:
        S() {};                   // Constructor? (the {} brackets) are needed here.

        // C++ 03
        // ========
        // Dont forget to declare these two. You want to make sure they
        // are unacceptable otherwise you may accidentally get copies of
        // your singleton appearing.
        S(S const&);              // Don't Implement
        void operator=(S const&); // Don't implement

        // C++ 11
        // =======
        // We can use the better technique of deleting the methods
        // we don't want.
    public:
        S(S const&)               = delete;
        void operator=(S const&)  = delete;

        // Note: Scott Meyers mentions in his Effective Modern
        //       C++ book, that deleted functions should generally
        //       be public as it results in better error messages
        //       due to the compilers behavior to check accessibility
        //       before deleted status
};

Se den här artikeln om när du ska använda en singleton: (inte ofta)
Singleton: Hur ska det användas

Se den här artikeln om initialiseringsordning och hur du hanterar:
Initialiseringsordning för statiska variabler
Hitta problem med statisk initialisering av C ++

Se den här artikeln som beskriver livstider:
Vad är livslängden för en statisk variabel i en C ++ -funktion?

Se den här artikeln som diskuterar några gängande implikationer för singletons:
Singleton-instans som förklaras som statisk variabel för GetInstance-metoden

Se den här artikeln som förklarar varför dubbelskontrollerad låsning inte fungerar på C ++:
Vad är alla vanliga odefinierade beteenden som en C ++ programmerare bör veta om?

klasser

class API
{
public:
    static API& instance();
    
    virtual ~API() {}
    
    virtual const char* func1() = 0;
    virtual void func2() = 0;
    
protected:
    API() {}
    API(const API&) = delete;
    API& operator=(const API&) = delete;
};

class WindowsAPI : public API
{
public:
    virtual const char* func1()  override { /* Windows code */ }
    virtual void func2() override { /* Windows code */ }    
};

class LinuxAPI : public API
{
public:
    virtual const char* func1() override { /* Linux code */ }
    virtual void func2() override { /* Linux code */ }    
};

API& API::instance() {
#if PLATFORM == WIN32
    static WindowsAPI instance;
#elif PLATFORM = LINUX
    static LinuxAPI instance;
#endif
    return instance;
}

I det här exemplet binder en enkel kompilatoromkopplare API klassen till lämplig underklass. På det här sättet kan man komma åt API utan att kopplas till plattformspecifik kod.

Trådsäker Singeton

C ++ 11

C ++ 11-standarderna garanterar att initialiseringen av funktionsomfångsobjekt initialiseras på ett synkroniserat sätt. Detta kan användas för att implementera en gängsäker singleton med lat initiering .

class Foo
{
public:
    static Foo& instance()
    {
        static Foo inst;
        return inst;
    }        
private:
    Foo() {}
    Foo(const Foo&) = delete;
    Foo& operator =(const Foo&) = delete;
};

Statisk deinitialiseringssäker singleton.

Det finns tider med flera statiska objekt där du måste kunna garantera att singleton inte förstörs förrän alla statiska objekt som använder singleton inte längre behöver det.

I detta fall kan std::shared_ptr användas för att hålla singletonet levande för alla användare, även när de statiska förstörarna kallas i slutet av programmet:

class Singleton
{
public:
    Singleton(Singleton const&) = delete;
    Singleton& operator=(Singleton const&) = delete;

    static std::shared_ptr<Singleton> instance()
    {
        static std::shared_ptr<Singleton> s{new Singleton};
        return s;
    }

private:
    Singleton() {}
};

OBS: Det här exemplet visas som ett svar i avsnittet Frågor och svar här.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow