2015-05-15 16 views
5

I Smart-Pointer in der folgenden Situation verwendet werden soll:Wie Smart-Pointer in dieser Situation verwenden

SOME_STRUCT* ptr = new SOME_STRUCT; 
    ptr->SOME_MEMBER = new BYTE[100]; 
    CallSomeAPI(ptr); 

nun die API kann entweder zurückgeben Fehler oder passiert erfolgreich, aber in diesen beiden Fällen i das Objekt löschen möchte Eine Möglichkeit kann sein, eine Löschanweisung während eines Fehlerausgangs und während eines normalen Ausgangs zu schreiben.

Aber wie kann ich einen intelligenten Zeiger für diese Zeiger verwenden? Mit intelligenten Zeigern meine ich unique_ptr, shared_ptr, etc. was auch immer funktionieren kann!

Danke!

+1

Warum Sie eine 'std :: unique_ptr' verwenden? Die neuen Smart Pointer sollten nicht wirklich als Ersatz für den normalen Pointer gesehen werden, sondern eher als Umgang mit dem Besitz: Kann eine Ressource (Speicher, Datei, Gerät usw.) mehreren Eigentümern gehören ('std :: shared_ptr') oder von nur einem einzigen Besitzer ('std :: unique_ptr') gleichzeitig? –

+0

Eigentlich möchte ich einen intelligenten Zeiger verwenden, um die Zuordnung automatisch zu entziehen, nicht unbedingt unique_ptr, mein Hauptziel ist automatische Bereinigung und nicht Besitz. Ich habe die Frage jetzt überarbeitet, um klarer zu sein. – shaarang

+0

Mit den intelligenten Zeigern * müssen * Sie wirklich über Besitz denken. Wenn Sie zum Beispiel ein 'std :: unique_ptr' an eine Funktion übergeben, wird die Eigentümerschaft in diese Funktion verschoben und das Objekt wird zerstört, sobald die Funktion zurückkehrt.Wenn Sie 'std :: shared_ptr' verwenden, wird das Objekt (oder der Speicher) nicht gelöscht, bis * alle * Kopien dieses freigegebenen Zeigers zerstört wurden, wenn es einen gibt, auf dem der Speicher noch zugewiesen wird. –

Antwort

2

Ich nehme an, Sie können SMOE_STRUCT nicht ändern, um einen Destruktor hinzuzufügen. Damit haben Sie zwei Optionen: einen benutzerdefinierten Löschvorgang und eine Kapselung.

Erstens könnten Sie eine benutzerdefinierte deleter für die Verwendung mit std::unique_ptr erstellen:

struct SOME_STRUCT_Deleter 
{ 
    void operator() (SOME_STRUCT *p) const 
    { 
    delete[] p->SOME_MEMBER; 
    delete p; 
    } 
}; 

std::unique_ptr<SOME_STRUCT, SOME_STRUCT_Deleter> ptr{new SOME_STRUCT}; 
ptr->SOME_MEMBER = new BYTE[100]; 
CallSomeAPI(ptr.get()); 

Wenn Sie feststellen, dass, im Gegensatz zu der Situation in Ihrer Frage beschrieben, Miteigentum Sie passen würde besser als ausschließliches, können Sie die deleter mit einem shared_ptr als auch, wie folgt aus:

std::shared_ptr<SOME_STRUCT> ptr{new SOME_STRUCT, SOME_STRUCT_Deleter{}}; 
ptr->SOME_MEMBER = new BYTE[100]; 
CallSomeAPI(ptr.get()); 

eine zweite Option, die ich bevorzugt zu finden, ist zu wickeln SOME_STRUCT:

struct SOME_STRUCT_plus_plus 
{ 
    SOME_STRUCT s; 
    ~SOME_STRUCT_plus_plus() 
    { 
    delete[] s.SOME_MEMBER; 
    } 

    SOME_STRUCT_plus_plus() 
    { 
    s.SOME_MEMBER = new BYTE[100]; 
    } 
}; 

std::unique_ptr<SOME_STRUCT_plus_plus> ptr{new SOME_STRUCT_plus_plus}; 
CallSomeAPI(&ptr->s); 

Sie könnten sogar „wrap“ es SOME_STRUCT_plus_plus, indem sie stammen aus SOME_STRUCT, anstatt sie zu aggregieren, die Sie ohne die Notwendigkeit, den direkten Zugriff auf Mitglieder durch s gehen würde. Gleichzeitig könnte es zu Speicherlecks kommen, wenn jemand SOME_STRUCT_plus_plus* auf SOME_STRUCT* und dann delete auf ihn wirft.

+0

Ich hätte die Wrapper-Klasse schreiben können, aber ich bevorzuge das nicht, aber ich mag die Custom-Deleter-Methode mehr ;-) aber kann das Gleiche mit Witz arbeiten h shared_ptr auch? – shaarang

+0

@shaarang Ja, es kann auch mit 'shared_ptr' arbeiten. Sie müssen das Löschobjekt explizit angeben, wenn Sie den gemeinsamen Zeiger erstellen, aber Sie müssen seinen Typ nicht im Typ des 'shared_ptr' angeben. Zu der Antwort hinzugefügt. – Angew

+0

Aber ich bevorzuge die Deleter-Methode, weil das meine Frage beantwortet und ich werde diese Methode basierend auf der Gesamtstruktur meines Codes verwenden. – shaarang

3

Sie können einen benutzerdefinierten Deleter für unique_ptr schreiben.

struct my_deleter { 
    void operator()(SOME_STURCT* ptr) const { 
     delete[] ptr->SOME_MEMBER; 
     delete ptr; 
    } 
}; 

using my_ptr = std::unique_ptr<SOME_STRUCT, my_deleter>; 

und ich würde vorschlagen, new SOME_STRUCT; zu new SOME_STRUCT{}; Ändern SOME_MEMBER-nullptr auf Standard zu initialisieren.

Ich bin nicht 100% glücklich mit dieser Lösung, also vielleicht in scope_guard oder schreiben Sie eine Wrapper-Klasse für Ihre Struktur.

1

Hier, so scheint es, dass alle auf dem Stapel sein kann:

SOME_STRUCT ptr;   // or auto ptr = std::make_unique<SOME_STRUCT>(); 
BYTE bytes[100];   // or std::vector<BYTE> bytes(100); 
ptr.SOME_MEMBER = bytes; // or ptr->SOME_MEMBER = bytes.data(); 
CallSomeAPI(&ptr);  // or CallSomeAPI(ptr.get()); 
+0

:-) Es ist nur verengte Version der Frage, die ich Ihnen, der Wert 100 ist nicht festgelegt und ist eigentlich [nCount], so kann es nicht eine Antwort sein. – shaarang

+0

Ja, ich habe gerade gemerkt, dass Vektor <> helfen kann, alle auf Stapel zu bringen, auch das kann der Weg sein! Vielen Dank! – shaarang

Verwandte Themen