2016-07-21 18 views
1

Ich habe diese link über neue gelesen und in C++ löschen. Es gibt einen Code, der das Singleton-Muster implementiert. Ich habe diesen Code getestet:Problem beim Test "Singleton mit neuen und löschen (C++)"

#include <iostream> 
#include <memory> 

class Singleton { 
    static Singleton *instance; 
    static std::size_t refcount; 
    std::string _s; 

    public: 
    void setS(std::string s) { _s = s; } 
    std::string getS() { return _s; } 
    static void *operator new(std::size_t nbytes) throw (std::bad_alloc) { 
     std::cout << "operator new" << std::endl; 
     if (instance == nullptr) { 
      std::cout << "operator new nullptr" << std::endl; 
      instance = ::new Singleton; // Use the default allocator 
     } 
     refcount++; 
     return instance; 
    } 

    static void operator delete(void *p) { 
     std::cout << "operator delete" << std::endl; 
     if (--refcount == 0) { 
      std::cout << "operator delete" << refcount << std::endl; 
      ::delete instance; 
      instance = nullptr; 
     } 
    } 
}; 

Singleton *Singleton::instance = nullptr; 
std::size_t Singleton::refcount = 0; 

int main() { 
    Singleton* s = new Singleton; 
    //Singleton* t = new Singleton; 
    s->setS("string s"); 
    std::cout << "s " << s->getS() << std::endl; 
    Singleton* t = new Singleton; 
    std::cout << "t " << t->getS() << std::endl; 
    return 0; 
} 

Aber das Ergebnis ist:

operator new 
operator new nullptr 
s string s 
operator new 
t 

Warum t nicht drucken "string s"? Wenn ich die Kommentarzeile ändere, kann t "string s" ausgeben.

+0

Was ist '* s == * t'? – user4759923

+0

Wie werden Stack-Instanzen berücksichtigt? – user2672165

+0

@ user4759923: * s und * t sind identisch, nur einer. Aber es gibt keinen Operator == für Singleton. Wenn Sie diesen Operator definieren, hängt das Ergebnis von Ihnen ab. – aviit

Antwort

2

Die Anweisung new Singleton ruft operator new auf, um Speicher zu erhalten, und initialisiert dann die nicht statischen Member des Objekts mit dem Standardkonstruktor.

Da _s nicht statisch ist, wird es jedes Mal neu initialisiert, wenn eine neue Singleton erstellt wird. Dies führt zu einer leeren Zeichenfolge für t.

Es ist sehr wahrscheinlich, dass UB den Platz für das _s Element auf diese Weise wiederverwenden kann.

+0

Der Speicher ist derselbe, aber der Konstruktor wird für jeden neuen Ausdruck aufgerufen, der alle nicht statischen Elemente (neu) initialisiert. – aviit