2015-07-12 11 views
5

Wiem, że to bardzo głupie pytanie o wzór singletonowy, ale wciąż jest to pierwszy wybór ankietera. Czy możesz dać mi znać w poniższym fragmencie kodu?Pytanie dotyczące pojedynczego zachowania związane z zapytaniem

(1) Po usunięciu obiektu singleton wciąż mogę wywołać metodę show() i działa poprawnie.

delete obj; 
obj=NULL; 
obj->show(); 

(2) Po utworzeniu obj1 obiekt dlaczego nie jestem w stanie wydrukować zawartość acquire_lock i funkcji release_lock nawet statment print „One Time” zostanie wydrukowany raz i jeśli zwiększamy licznik I wtedy zamiast 2 go drukuje tylko 1, dlaczego?

Foo *obj1=MySingleton<Foo>::GetInstance(); 

(3) użycie unique_ptr z pojedynczym obiektem będzie miało negatywne implikacje.

fragment kodu:

#include <iostream> 
#include <fstream> 
#include <memory> 
#include <string> 

using namespace std; 

static int i; 

class Lock 
{ 
public: 
    Lock(){}; 
    ~Lock(){}; 

    void acquire_lock() 
    { 
     cout<<"aquired lock for class"; 
    } 

    void release_lock() 
    { 
     cout<<"released lock for class"; 
    } 

}; 

class Foo 
{ 
public: 
    void show() 
    { 
     cout<<"\ndone\n"; 
    } 
}; 

template <class T> 
class MySingleton 
{ 
protected: 

    MySingleton() {} 

private: 

    //holds one and only object of MySingleton 
    static T* m_pOnlyOneInstance; 
    MySingleton(const MySingleton <T> &) {}; 
    MySingleton <T> & operator=(const MySingleton <T> &) {}; 
    ~MySingleton() {}; 

public: 

    static T * GetInstance(); 

    void foo() 
    { 
     cout<<"Mohan"; 
    } 
}; 


template <class T> 
T* MySingleton<T>::GetInstance() 
{ 
    Lock lock; 
    if (m_pOnlyOneInstance == NULL) 
    { 
     lock.acquire_lock(); 
     cout<<"one Time"<<endl; 
     i++; 
     if(m_pOnlyOneInstance == NULL) 
     { 
      m_pOnlyOneInstance = new T(); 
     } 
     lock.release_lock(); 
    } 
    return m_pOnlyOneInstance; 
} 

template <class T> T* MySingleton<T> :: m_pOnlyOneInstance=NULL; 

int main() 
{ 
    //std::unique_ptr <Foo> obj (MySingleton<Foo>::GetInstance()); 
    Foo *obj=MySingleton<Foo>::GetInstance();  
    //obj->show(); 
    delete obj; 
    obj=NULL; 
    obj->show(); 
    cout<<"\ncalling again\n"; 
    Foo *obj1=MySingleton<Foo>::GetInstance(); 
    obj1->show(); 
    cout<<"i="<<i; 
    return 1; 
} 

Uwaga: Funkcja blokady związane są jedynie atrapę realizację.

Odpowiedz

0

(1) Wywołanie nie powiedzie się, jeśli rzeczywiście użyje go do wykonania połączenia lub połączenia.

Najpierw wywołanie to jest funkcją nie-wirtualną, więc wskaźnik obj nie jest potrzebny do znalezienia funkcji. Kompilator już zorientował się w czasie kompilacji, do której funkcji należy wywoływać.

Po drugie funkcja nie uzyskuje dostępu do żadnych zmiennych członkowskich klasy, więc gdy otrzyma wskaźnik o wartości NULL, nigdy go nie używa.

BTW, wygląda na to, że ten kod próbuje użyć szablonu MySingleton, aby uczynić inne klasy singletonami, ale tak naprawdę nie uniemożliwia tworzenia kopii lub tworzenia obiektów za pomocą innych sposobów, więc nie jest to prawdziwe singleton. Jedyne, co robi, to zawsze zwracać ten sam wskaźnik.

Inne BTW, drugie połączenie z MySingleton<Foo>::GetInstance() zwraca kopię wskaźnika, który wcześniej usunąłeś, gdy robiłeś delete obj. obj został ustawiony na wartość NULL po usunięciu, ale oryginalny wskaźnik w szablonie MySingleton nadal wskazuje usunięty obiekt, więc drugie wywołanie funkcji GetInstance z przyjemnością zwróci teraz nieprawidłowy wskaźnik.

2
  1. Należy pamiętać, że obj->show() jest odpowiednikiem Foo::show(obj). Oba wyrażenia ustawiają this na wartość obj w ramach funkcji składowej show. Co by ustawić ustawienie this na NULL w ramach show? Nic, ponieważ nigdy nie odwołujesz się do this.
  2. Cóż, pomyśl o całym powodzie, dla którego najpierw używałbyś wzoru singleton - do zainicjowania czegoś najwyżej raz. To "jednorazowe" polecenie print znajduje się w kodzie, w którym obiekt jest instancjonowany, więc oczywiście nie zostanie wykonany po raz pierwszy. Spójrz na logikę GetInstance. Jeśli instancja nie istnieje, tworzy instancję klasy (niechlujnie ... ale działa), a następnie instancja istnieje. W przeciwnym razie nic nie robi.
  3. To pytanie jest bardzo niejasne, ale zakładam, że masz na myśli "jakie są negatywne konsekwencje robienia std::unique_ptr<Foo> obj = MySingleton<Foo>::GetInstance();?"Jak widać z poziomu reference dla unique_ptr, jego celem jest przejęcie na własność dynamicznie przydzielonego zasobu, co jest niewątpliwie spowodowane działaniem pojedynczych obiektów. w tym przypadku) jest dzielona między dowolną liczbę wywołujących, klasa singleton jest jedyną, która powinna zarządzać zasobem instancji - jest to podstawowa niezmiennik wzorca singleton. Jeśli użyjesz unique_ptr, gdy tylko obj wykracza poza zakres , usunie instancję automatycznie, niezależnie od tego, czy Twój program odwołuje się do instancji zwalnianej teraz gdzie indziej.
+0

Dzięki za wyjaśnienia. Dla punktu (1), jeśli nie ustawię wartości NULL nadal działa i dla punktu (2), jeśli usuniemy obiekt singleton, to muszę ustawić m_pOnlyOneInstance = NULL, wykonując metodę statycznego czyszczenia dla celu usuwania pojedynczych obiektów. – user3522354

+0

(1) W porządku, funkcja składowa nigdy nie odwołuje się do "tego", więc naturalnie nie ma znaczenia, jakiej wartości używasz. (2) Tak, w przeciwnym razie funkcja 'GetInstance' nie będzie miała pojęcia, czy musi ponownie utworzyć klasę później. Ale funkcja statycznego czyszczenia może być użyta tylko wtedy, gdy masz pewność, że żadne inne zmienne nie odwołują się do singletonu, więc nie poleciłbym tego. – mooiamaduck

+0

Czy chcesz powiedzieć, że nie musimy wykonywać funkcji czyszczenia statycznego, aby wyraźnie usunąć obiekt singleton podczas zamykania aplikacji. – user3522354

0

Twoja klasa singleton powinna mieć prywatną konstrukcję lub i destruktor. Destruktor powinien obsługiwać wszelkie operacje czyszczenia pamięci, gdy kończy się zakres singletonu, więc nie ma potrzeby jawnego usuwania go. Usunięcie go może być niebezpieczne, gdy inne obiekty wciąż mają dostęp do singletonu po usunięciu. Możesz uzyskać niezdefiniowane zachowanie, gdy wykonałeś polecenie "delete obj" i "obj = null", ponieważ przeciążony operator przypisania i destruktor są prywatne.

+0

Zgadzam się, że musimy usunąć metodę statyczną wewnątrz klasy singleton, aby usunąć obiekt, ale jak wyjaśniłem w moim pytaniu, jest to wyłącznie pytanie dotyczące wywiadu. – user3522354

1

Nie jest to właściwy sposób na usunięcie pojedynczego obiektu, należy napisać poniższą metodę, aby usunąć instancję, a następnie uruchomić program.

static void cleanup() 
    { 
     delete m_pOnlyOneInstance; 
     m_pOnlyOneInstance= NULL; 

    } 

Oto wynik:

aquired blokada Czas classone wydany blokady dla klasy wykonanej

wzywającą ponownie aquired blokada Czas classone wydany blokady dla klasy wykonanej i = 2

+0

Dziękuję za porządne oczyszczenie i teraz otrzymuję prawidłowy wynik. – user3522354

Powiązane problemy