C++ Delete a return value

kiname

Cadet 3rd Year
Registriert
Nov. 2014
Beiträge
56
Hallo,

ich bin relativ neu in c++.
ich versuche eine eigene String Klasse zu schreiben (nur ein bisschen die Sprache kennen lernen).
ich habe folgendes Problem:
Code:
private:
	char *str;
.
.
.
	MyString operator+(const MyString & t)
	{
		char* newMyString = new char[strlen(str) + strlen(t.str) + 1];
		strcpy(newMyString , str);
		strcat(newMyString , t.str);
		return newMyString ;
		delete[] newMyString ;
	}
Hier versuche ich mit dem + operator 2 MyString Objekte zu verbinden. Das Funktioniert ja auch jedoch soll mein newStr char* aus dem Speicher gelöscht werden.
Meineswissens wird ja der Code, der nach dem return Schlüsselwort kommt nicht ausgeführt.
Bisher in C# und Java habe ich mir um solche sachen keine Gedanken gamacht aber in c++ muss man ja alles "von Hand" freigeben.

Weiß jemand wie ich trotzdem den Speicher Freigeben kann?
 
Mit "return" wird bereits aus der Funktion herausgesprungen. Der Delete-Aufruf erfolgt als gar nicht mehr. Theoretisch müsste der Variable gar nicht mehr aus dem Heap entfernt / gelöscht werden, wenn du einfach den Pointer übergibst.
 
Davon ab, der Rückgabewert ist deine Klasse und du gibst nen String/char-Pointer zurück. Überleg nochmal genau. Funktioniert zwar mit nem passenden Konstruktor (der implizit aufgerufen wird), allerdings ist der Stil nicht wirklich schön und wenn du den Speicher nicht im Konstruktor frei gibst bzw. zuweist, hast du n Memory Leak.
 
kiname schrieb:
ich versuche eine eigene String Klasse zu schreiben (nur ein bisschen die Sprache kennen lernen).

Hier versuche ich mit dem + operator 2 MyString Objekte zu verbinden. Das Funktioniert ja auch jedoch soll mein newStr char* aus dem Speicher gelöscht werden. Meineswissens wird ja der Code, der nach dem return Schlüsselwort kommt nicht ausgeführt.

IMHO nicht ganz richtige Herangehensweise. Du brauchst einen

MyString operator+(const MyString& a, const MyString & b) {
MyString temp;
// Kopiere a und b nach temp
...
...
return temp;​
}

Da must Du nix "freigeben". Die Speicherverwaltung übernimmt MyString::MyString(int len); und ~MyString();.
 
Zuletzt bearbeitet:
Weiterer Hinweis: Wenn Du einen Pointer auf einen Speicherbereich zurückgibst ist es idR. eine ganz schlechte Idee den Speicher am "Aufrufer vorbei" (der, der mit dem Rückgabewert arbeitet) wieder freizugeben. Mal angenommen dein delete[] nach dem return würde funktionieren:

Code:
char * getStringMemory(size_t size) {
    char * memory = new char[size];
    return memory;
    delete[] memory;
} 

int main (...) {
    size_t size = 128;
    char * my_memory = getMemory(size);
    // was ist nun mit my_memory? der speicher wurde ja bereits wieder freigegeben! 
    // jeder zugriff darauf sollte idealerweise mit einem Segfault das Programm abbrechen lassen
}
 
0xffffffff schrieb:
Weiterer Hinweis: Wenn Du einen Pointer auf einen Speicherbereich zurückgibst ist es idR. eine ganz schlechte Idee den Speicher am "Aufrufer vorbei" (der, der mit dem Rückgabewert arbeitet) wieder freizugeben. Mal angenommen dein delete[] nach dem return würde funktionieren:

In diesem und allen Paralleluniversen wird nach einem RETURN innerhalb der gleichen Funktion nichts mehr ausgeführt. Deshalb braucht man hier nichts annehmen. Prinzipiell könnte man bei Type-Match den Pointer auf die gleiche Adresse legen, dann fällt natürlich auch bereits der RETURN-Sprung weg, da die Aufgabe abgeschlossen ist - ist natürlich Bad Practice.

Aber bitte nichts annehmen, was im Leben nie und nimmer zutreffen kann. Vor Allem sollte man einem Anfänger solche Flausen gar nicht erst in den Kopf setzen.

@kiname: Es freut mich immer, wenn sich Neulinge weiterentwickeln wollen. Im Bezug auf C/C++ empfehle ich dir zwingend, dich mit Speicher-Management auseinander zu setzen. Das ist hier das A-und-O und dein ewiger Begleiter.
 
inciter schrieb:
In diesem und allen Paralleluniversen wird nach einem RETURN innerhalb der gleichen Funktion nichts mehr ausgeführt. Deshalb braucht man hier nichts annehmen.

Das ist mir schon klar Meister. Mir ging es darum ihm die Flausen aufzuzeigen die er sich da gedacht hat, da er mit dem Gedankengang den er beim Programmieren hatte garantiert demnächst in ein Use-After-Free rennt. Dass das mit dem return und mein beispiel prinzipiell Schwachsinn ist darüber brauchen wir nicht reden :) Ich wollte ihm die Gefahr nur an seinem eigenen Code verdeutlichen.
 
kiname schrieb:
Bisher in C# und Java habe ich mir um solche sachen keine Gedanken gamacht aber in c++ muss man ja alles "von Hand" freigeben.
Und genau das ist der Denkfehler: In 99,9% der Fälle sollte ein Programm so geschrieben sein, dass man den Speicher nicht manuell freigeben muss (RAII ist hier das Stichwort). Insbesondere Dank unique_ptr und shared_ptr sind new und delete in modernen C++ Programmen praktisch überflüssig geworden.

Code:
MyString operator+(const MyString & t)
{
	std::unique_ptr<char[]> newMyString = std::unique_ptr<char[]>(new char[ strlen(str) + strlen(t.str) + 1] );
	strcpy(newMyString.get() , str);
	strcat(newMyString.get() , t.str);
	return newMyString ;		
}

Man kanns auch kürzer schreiben:
Code:
	auto newMyString = std::make_unique<char[]>(strlen(str) + strlen(t.str) + 1);

Ganz davon abgesehen wäre es aber - wie von blöderidiot vorgeschlagen - ohnehin idiomatischer, innerhalb von operator+ ein Mystring Objekt auf dem Stack anzulegen und das dann zurückzuliefern. Allgemein werden Objekte in C++ wesentlich seltener auf dem Heap angelegt als in java oder c#.

Ich würde dir auch empfehlen, intern kein char array, sondern einen std::vector<char> zu verwenden. Dann bekommst du nen korrekten Copy/Move Konstruktor/assignment operator um sonst.
Ergänzung ()

@inciter: Er liefert keinen Pointer auf einen Speicherbereich zurück. Das array wird genutzt um ein temporäres MyString Objekt zu initialisieren, das dann by value zurückgegeben wird - ansonsten würde der Code erst garnicht compilieren.
 
Zuletzt bearbeitet:
Weiß jemand wie ich trotzdem den Speicher Freigeben kann?
Durch den Destruktor, was sonst?!?

Miuwa hat eigentlich schon alle wichtigen Stichworte genannt, damit Du deine eigene Stringklasse schreiben kannst: RAII (sehr wichtig!!), rule of three/five, std::vector, std::unique_ptr, std::make_unique, operator overloading und eventuell noch boost::operators.

... in c++ muss man ja alles "von Hand" freigeben.
Definitv nein. Wenn Du mit rohen Zeigern oder mit new/delete rumhantierst machst du was falsch.
 
Zurück
Oben