Es ist subtiler als die anderen Antworten vermuten lassen. Es gibt keine absolute Trennung zwischen Daten auf dem Stapel und Daten auf dem Heap, basierend darauf, wie Sie sie deklarieren. Beispielsweise:
std::vector<int> v(10);
Im Hauptteil einer Funktion wird ein vector
(dynamisches Array) von zehn Ganzzahlen auf dem Stapel deklariert . Der von der verwaltete Speicher vector
befindet sich jedoch nicht auf dem Stapel.
Ah, aber (die anderen Antworten deuten darauf hin) die Lebensdauer dieses Speichers ist durch die Lebensdauer des Speichers selbst begrenzt vector
, der hier stapelbasiert ist. Daher spielt es keine Rolle, wie er implementiert wird - wir können ihn nur als stapelbasiertes Objekt behandeln mit Wertesemantik.
Nicht so. Angenommen, die Funktion war:
void GetSomeNumbers(std::vector<int> &result)
{
std::vector<int> v(10);
// fill v with numbers
result.swap(v);
}
Alles mit einer swap
Funktion (und jeder komplexe Werttyp sollte eine haben) kann als eine Art wiederbindbarer Verweis auf einige Heap-Daten unter einem System dienen, das einen einzelnen Eigentümer dieser Daten garantiert.
Daher besteht der moderne C ++ - Ansatz darin, die Adresse von Heap-Daten niemals in nackten lokalen Zeigervariablen zu speichern. Alle Heap-Zuordnungen müssen in Klassen ausgeblendet sein.
Wenn Sie dies tun, können Sie sich alle Variablen in Ihrem Programm als einfache Werttypen vorstellen und den Heap insgesamt vergessen (außer beim Schreiben einer neuen wertähnlichen Wrapper-Klasse für einige Heap-Daten, was ungewöhnlich sein sollte). .
Sie müssen lediglich ein spezielles Wissen behalten, um die Optimierung zu unterstützen: Wenn möglich, anstatt eine Variable einer anderen wie folgt zuzuweisen:
a = b;
Tauschen Sie sie so aus:
a.swap(b);
weil es viel schneller ist und keine Ausnahmen auslöst. Die einzige Voraussetzung ist, dass Sie nicht b
weiterhin denselben Wert beibehalten müssen ( a
stattdessen wird der Wert abgerufen, der in den Papierkorb verschoben wird a = b
).
Der Nachteil ist, dass Sie bei diesem Ansatz gezwungen sind, Werte von Funktionen über Ausgabeparameter anstelle des tatsächlichen Rückgabewerts zurückzugeben. Aber sie beheben das in C ++ 0x mit rWert-Referenzen .
In den kompliziertesten Situationen von allen würden Sie diese Idee auf das äußerste Extrem bringen und eine intelligente shared_ptr
Zeigerklasse verwenden, wie sie bereits in tr1 enthalten ist. (Obwohl ich behaupten würde, dass Sie, wenn Sie es zu brauchen scheinen, möglicherweise außerhalb des Sweetspots der Anwendbarkeit von Standard C ++ umgezogen sind.)