C++: destructer Aufruf von member elements ?

rubricanis

Homo ludens
Eine kurze - vielleicht dumme - Frage. In folgendem Fall frage ich mich ob der destructor der strings automatisch aufgerufen wird bzw. wie das zu handhaben ist.
Code:
class X {

    std::string path1, path2;

     X(std::string path){
       ...
        path1 = path + "xxx";
        path2 = path + "yyy";
     }

     ~X (){
        ???
      }

};
 
Ja, sobald ein Objekt vom Typ X zerstört wird, werden auch die Desktrukotr der Strings automatisch aufgerufen nachdem der Destruktor von X aufgerufen wurde. Das ist das schöne an RAII. Schade dass nicht jede Sprache das unterstützt.:(

Der Compiler erstellt Code wie diesen hier:
Code:
class X {

std::string path1, path2;

X(std::string path){
...
path1 = path + "xxx";
path2 = path + "yyy";
}

~X (){
...

path2.~string();
path1.~string();
}

};
 
Der String wird mit zerstören des Objekts mit zerstört.

edit: schlimmer Fehler korrigiert...
 
Aber nur, wenn es auch echte Objekte sind ;)

Wenn std::string * vorkommt, beispielsweise weil sich mehrere Objekte eine einzige String-Instanz teilen sollen, muss delete (im letzten) Destruktor manuell aufgerufen werden, aber in dem Fall bietet sich std::shared_ptr an, damit erspart man sich das delete-Hickhack (vor allem, wenn man exceptions benutzt).
 
std::string * wäre ja auch kein RAII.

Da nimmt man dann std::shared_ptr. Wenn man den String nur anlegen muss und selber nicht mehr braucht kann man das auch mit move-Semantik machen.
 
Ja, auch wenn es etwas Speicher kostet und auch an der Performance etwas zerrt... RAII ist für "alltägliches C++" schon quasi Pflicht.

Dieses:

std::string* MyClass::gibtMirEinenStringAberIchSagDirNurInDerAPIDokuObDuDenLöschenMusstOderNicht() { return str; }

ist einfach nur ätzend xD
 
Nur mal so als Randbemerkung aus einer anderen Welt. In z.B. Modula-3 sieht der destructor code für das Objekt, egal ob nun mit oder ohne String wie folgt aus:

Code:
{* Nichts zu sehen, bitte weitergehen *}

(Wobei ich einräume, dass die Kommentar-Syntax bei Wirthschen Sprachen mit zum Hässlichsten und Umständlichsten überhaupt gehört. C/C++ (//) z.B. und Ada (--) sind da erheblich besser).
 
Echte und unechte Objekte gibts nicht... Es gibt welche auf dem Heap und welche auf dem Stack. Mit unecht war in dem Zusammenhang gemeint, dynamisch alloziert und per Pointer angesprochen.

Wenn du einen std::string* hast und dein Objekt wird zerstört, dann wird der Speicherbereich des Pointers freigegeben (aber eben nicht das Objekt auf welches er zeigt).

edit: Woher sollte er auch wissen ob der Pointer nun auf ein bereits erzeugtes Objekt zeigt das zerstört werden kann oder ob er einfach in die Weltgeschichte zeigt... Im zweiten Fall würde ein Zerstörungsversuch zum Absturz führen...
 
So "Faustregel": Für jedes "new" ein "delete".

Hast du kein new, dann brauchst du auch kein delete.
auto foo = std::unique_ptr<MyStupidType>{new MyStupidType};

Auch hier braucht man sich nicht selber ums delete zu kümmern. Obwohl man das new selber gemacht hat.
 
Nuke, da warst du schneller! :) Hatte den von dir zitierten Teil gelöscht nachdem ich einen Moment darüber nachgedacht hatte. Nachdenken vorm schreiben ist auch hier von Vorteil. :rolleyes:
 
@-Nuke-
Stimmt. Irgendwie habe ich mir die make_unique, make_shared usw. noch nicht angewöhnt.

EDIT:
Könnt Ihr mir zwischen den Posts nicht ein paar Sekunden Zeit geben? Ich muss ständig die Posts umbauen weil jemand schneller war. :P
 
Ja, die sind halt extrem cool. Auch wenn du eine Liste hat:

Code:
std::vector<MyClass> mylist;
mylist.push_back(MyClass(arg1, arg2, arg2))

vs:

Code:
std::vector<MyClass> mylist;
mylist.emplace_back(arg1, arg2, arg2)

Steckt im Prinzip das Gleiche in Grün dahinter.
 
Was sind 'echte' und was sind 'unechte' Objekte ?

Ich wollte damit damit direkt eingebettete Objekte von Zeigern abheben:
Code:
struct Foo {
    std::string name;
}
vs
Code:
struct Bar {
    std::string *nameptr;
}

Der Rest wurde schon ziemlich ausgelatscht, smartptr anstatt rawptr usw.…
Nur eine Anmerkung aus Prinzip: std::make_unique wurde in C++11 vergessen, wenn man also Cross-Platform Code schreiben möchte kann man das leider nicht verwenden, weil Microsoft mit ihrem Compiler nicht zu Potte kommt. Das ist zwar relativ einfach selber via implementierbar, aber ich persönlich nutze da lieber die von Kamikaze vorgeschlagene Variante.
 
Nur eine Anmerkung aus Prinzip: std::make_unique wurde in C++11 vergessen, wenn man also Cross-Platform Code schreiben möchte kann man das leider nicht verwenden, weil Microsoft mit ihrem Compiler nicht zu Potte kommt. Das ist zwar relativ einfach selber via implementierbar, aber ich persönlich nutze da lieber die von Kamikaze vorgeschlagene Variante.

Ja, das stimmt schon, aber dann sollte man auch C++11 nicht nutzen. Ist bei MS auch noch nicht vollständig drin. Und beim GCC ist der Status zwar auch "vollständig", aber sowas wie std::thread schmiert bei mir auf dem Raspberry Pi mit "pure virtual method called" ab :D Auf x86_64 geht es aber.
 
Zurück
Oben