2017-12-05 4 views
0

Ich habe eine Hierarchie, wo A ist eine abstrakte Klasse und B, C und sind Nachkommen von A. Ich habe eine Klasse Controller (MVC-Muster) mit einem gemeinsamen Zeiger auf A:C++ shared ptr release auf mehrere Referenzen

class Controller { 

private: 
int it; 
std::shared_ptr<A> theBase; 

public: 
void doCall(); 
//more code 

} 

Innen doCall() ich dies tun:

void doCall() { 

    switch (it) { 
    case 4: 
     theBase = std::make_shared<B>(B(8)); 
     break; 
    case 3: 
     theBase = std::make_shared<C>(C(6)); 
     break; 
    default: 
     theBase = std::make_shared<D>(D(0)); 
     break; 
    } 

    theBase->method(); 

} 

Auf diese Weise ich richtig intelligente Zeiger verwenden kann, und ich kann Vererbung um die Klasse zu bekommen, die ich brauche, nach dem Wert it.

Nehmen wir an, ich diesen Code nennen:

Controller x; 
x.doCall(); 
x.doCall(); 

ich doCall() zweimal nenne, so dass ich in der switch zweimal werde. Dies bedeutet, dass std::make_shared zweimal aufgerufen wird und theBase zugewiesen wird. Ist das sicher?

Wenn ich zum ersten Mal doCall() aufrufen, habe ich einen gemeinsamen Zeiger. Das zweite Mal bin ich ein std::shared_ptr zu theBase zuweisen, und ich frage mich: Ist der alte Zeiger (der eine der ersten Aufruf) zerstört und eine neue erstellt? Oder muss ich so etwas tun?

if (*theBase != nullptr) { 
    theBase.reset(); //delete the old one; 
} 

switch (it) { /* ... */} 

Jedes Mal doCall() heißt, ich habe ein neues Objekt erstellen, die eine Unterklasse von theBase ist. Mache ich es richtig?

+3

Lesen Sie: http://en.cppreference.com/w/cpp/memory/shared_ptr/operator%3D _ "Wenn * das bereits ein Objekt besitzt und es das letzte shared_ptr ist, das es besitzt, und r nicht ist das gleiche wie * das, das Objekt wird durch den eigenen Deleter zerstört. "_ –

+0

@RichardCritten Wie ich vermutete, gibt es keine Notwendigkeit, reset() aufzurufen, wenn ich theBase = std :: make_shared zum zweiten Mal den alten Zeiger gebe gelöscht und eine neue erstellt. Keine Speicherlecks und wir sind alle glücklich. Vielen Dank! –

Antwort

4

Sie müssen nichts tun. Wenn Sie den neu erstellten shared_ptr dem theBase zuweisen, wird der Referenzzähler des alten Zählers dekrementiert. Der Zähler des alten Zählers ist jedoch 1 (wenn wir annehmen, dass Sie ihn nicht woanders referenzieren). Der Zähler erreicht 0 und der Destruktor wird aufgerufen.

am folgenden Code Werfen Sie einen Blick:

#include <stdio.h> 
#include <memory> 

class myClass 
{ 
public: 
    myClass(int i) : m_i(i) { printf("Constructed %d\n", m_i); } 
    ~myClass() { printf("Destructed %d\n", m_i); } 

    int m_i; 
}; 

int main() 
{ 
    std::shared_ptr<myClass> ptr = std::make_shared<myClass>(5); 

    ptr = std::make_shared<myClass>(10); 
} 

Die Ausgabe lautet:

Constructed 5 
Constructed 10 
Destructed 5 
Destructed 10 

Der erste Zeiger kurz nach dem zweiten (genauer gesagt erstellt wird zerstört, wenn zugeordnet, das ist, wo der Zähler des ersten wird dekrementiert).

Verwandte Themen