2016-05-07 8 views
1

Ich habe einen Hintergrund in C und versuche, C++ - Klassen zu verstehen und wie die Destruktoren als Objekte aufgerufen werden, die den Bereich verlassen. Als Randbemerkung würde ich angesichts der Art dessen, was ich versuche, lieber keine STL-Strukturen wie std :: array <> oder std :: vector <> für die Datencontainer verwenden, die ich unten präsentiere.Stapel- und Heapzuweisungen von instanziierten Objekten C++

Hier ist ein Überblick auf hoher Ebene meines Verständnisses. Gegeben eine Klasse:

class some_class{ 
    public: 
     int * member; 
     size_t n_members; 

     some_class(size_t count) ... 
     ~some_class() ... 

     // a member function or operator overload 
     // that returns an instance of some_class 
     some_class do_something() 
} 

... 

some_class * container; 
// Some scope 
{ 
    some_class foo = some_class(); 
    some_class * bar = new some_class(); 
    container[0] = bar; 
} 

Wenn some_class foo den Umfang verlässt, wird der Destruktor aufgerufen. Wenn ich einen Zeiger auf eine Instanz some_class in container außerhalb des Bereichs speichern wollte, muss ich some_class bar auf dem Heap instanziieren, so dass Speicher nicht sofort beim Verlassen des Bereichs freigegeben wird - genau wie ich in C.

Jetzt ist der Zweck von some_class, eine beliebig große Menge von Daten zu halten, und so int * memberbenötigt auf dem Heap zugeordnet werden.

oben gegeben, den Konstruktor und Destruktor für some_class() so etwas wie folgt aussehen:

// some_class constructor 
some_class::some_class(size_t count) : n_members(count){ 
    member = new int[count]; 
} 

// some_class destructor 
some_class::~some_class(){ 
    delete[] member; 
} 

Nun mein Problem deutlich: Wenn ich brauche eine Instanz hinzufügen von some_class aus der do_something() Methode zurückgegeben, ich garantiert werde einen Speicherfehler haben (in diesem Fall eine Doppelfrei), weil do_something() gibt einen Stapel zugewiesene some_class:

some_class * container = new some_class[n]; 
// Some scope 
{ 
    some_class foo = some_class(); 
    some_class bar = foo.do_something(); 
    container[0] = &bar; // <-- I know this is stupid but that's the point of this question 
} 
delete[] container; 

Mein Weg, um dies istzu machengibt einen Zeiger auf eine Instanz von some_class zurück. Natürlich keine Lösung. Wie würde man eine solche Situation in echter C++ - Art richtig angehen?

Zum Beispiel, eine Sache, die ich gelesen habe, war die Verwendung von geteilten Zeigern oder eindeutigen Zeigern (oder Smart-Zeigern im Allgemeinen). Mein Verständnis ist jedoch, dass die Verwendung dieser Zeiger erfordert, dass Sie Ihr Objekt im Heap instanziiert haben. Es hilft auch nicht das ganze Problem über foo.do_something(), um einen Zeiger zurückgeben.

Wie auch immer, irgendwelche Gedanken würden geschätzt werden.

+0

* Wenn ich eine Instanz von some_class aus dem do_something() -Methode zurück hinzufügen müssen, ich garantiert bin einen Speicherfehler haben * Ja.Siehe [Die Dreiregel] (http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three), um das zu beheben. –

+0

Und dann: http://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11/4782927#4782927 –

+1

'Als eine Randnotiz, angesichts der Art von dem, was ich versuche ich zu tun, würde ich lieber keine STL-Strukturen verwenden. Wenn Sie kein C++ - Experte sind, können Sie unter einem Missverständnis leiden, dass wir korrigieren können. –

Antwort

0

Smart-Zeiger kann verwendet werden, Zeiger in some_class wie folgt zu halten:

#include <memory> 

class some_class{ 
    public: 
    // smart pointer instead of raw pointer 
    std::unique_ptr<int[]> member; 
    size_t n_members; 

    some_class(size_t count = 0) : member(new int[count]), n_members(count) {} 

    // destructor not needed 

    // a member function or operator overload 
    // that returns an instance of some_class 
    some_class do_something(); 
}; 

int main() 
{ 
    int n = 3; 
    // smart pointer instead of raw pointer 
    std::unique_ptr<some_class[]> container(new some_class[n]); 
    { 
    some_class foo = some_class(10); 
    some_class bar = foo.do_something(); 
    // use std::move to transfer pointer ownership 
    container[0] = std::move(bar); 
    } 
    // no need to delete 
} 
-4

verwenden ich in C++ beherrscht, sondern zog nach Java schon vor langer Zeit und mein C++ ist rostig jetzt :(.

Eine Sache, die Sie tun können einen Konstruktor ist zu erstellen, das ein Mitglied der Klasse übernimmt. Im Innern kopieren, nur die Objekte zu Ihrer neuen Instanz (auch ist es möglich, sie mit einer statischen Methode zu machen, anstatt den Konstruktor von Überlastung)

some_class::some_class(some_class* obj){ 
    member = obj->member; 
    n_members = obj->n_members; 
} 

So können Sie dies in Ihrem Code:..

some_class * container; 
// Some scope 
{ 
    some_class foo = some_class(); 
    some_class * bar = new some_class(); 
    container = new some_class(bar); 
} 

Hoffe, es funktioniert für Sie.

+0

Ja, dein C++ ist ziemlich rostig. Wenn alles, was Sie in Ihrem Kopierkonstruktor tun, eine stichwortartige Kopie ist, haben Sie der Situation überhaupt nicht geholfen, da dies genau der Kopierkonstruktor ist, den der Compiler automatisch generiert, und er wird für eine Klasse wie diese nicht korrekt funktionieren . Außerdem muss das Objekt als Referenz verwendet werden, da ein wertmäßiger Wert einen Kopierkonstruktor erfordert. –

+0

Wie wäre es mit SP, BP? Es würde das Problem lösen, aber ich bin nicht sicher, wie C++ es ist. – mhyst

+0

Ja, ich habe das * und das ->, -> vergessen. Aber im Ergebnis werden Ihre Downvotes dies zum letzten Mal machen, wenn ich versuche, eine C++ Frage zu beantworten. – mhyst

Verwandte Themen