new



  • Hallo,

    Ich frage mich wofür man new braucht.
    Ich weiß dass es sinnvoll ist Speicher dynamisch zu allokieren, aber vor welche Zeiger muss ich new schreiben. Ich meine ein Zeiger zeigt nur auf ein Element.
    Es handelt sich ja nicht um eine variable Größe die noch nicht bekannt ist.
    Irgendetwas scheine ich zu übersehen.

    Kann mir das jemand bitte erklären?

    Desweiteren wurde

    Koordinate *p = new Koordinate;
    p->x = 35; p->y = 28;
    Koordinate *pC = p; //wurde blau markiert
    delete p;
    pC->x = 47;

    als typischer Fehler angegeben.
    Ich hätte das so aber auch gemacht.
    Oder ist die eingeschobene Zeile, also die Kopie anlegen schon die Behebung des Fehlers, da wenn man wieder p benutzen würd, der Zeiger irgendwohin zeigt und es Probleme gibt.



  • Nackte new Befehle braucht man praktisch nie. C++ bietet viele Standardcontainer die implizit zwar new benutzen, welches man selbst aber bei der Benutzung der Container nie braucht.

    Zu deinem Beispiel:

    Der Zeiger p wird mit einem dynamisch allokierten Speicherbereich initialisiert, d.h. p zeigt auf eine gültige Adresse.
    Sobald delete für den Zeiger p aufgerufen wird, ist der allokierte Speicherbereich freigegeben was in der Praxis bedeutet, das ein Zugriff auf diesen Bereich einen Fehler darstellt (es ist undefiniert was passiert, wenn du auf einen derartigen Bereich zugreifst, es könnte alles passieren, praktisch würd dein Programm aber meistens abstürzen).

    Dadurch das du vor dem Löschen von p den Speicherbereich auf den er zeigt an pC weitergegeben hast, kannst du auch nach dem Löschen von p auf den Bereich zugreifen, was wie oben gesagt zu nicht definiertem Verhalten führt. Das ist immer schlecht und führt meistens zu einem Absturz.



  • Ravend schrieb:

    ... es sinnvoll ist Speicher dynamisch zu allokieren ...

    Diese Aussage ist falsch! Wenn immer es geht, sollte Speicher in C++ nicht dynamisch allokiert werden.



  • Genauer gesagt ist dynamische Allokation zwar sinnvoll, aber nicht manuell. Meist geschieht sie implizit; mit C++14 gibt es so gut wie keine Situationen mehr, wo man new oder delete im Code braucht.

    // Einzelnes Objekt
    T obj; // bevorzugen wenn möglich
    auto ptr = std::make_unique<T>();
    
    // Container
    std::vector<T> container;
    


  • Ravend schrieb:

    Ich frage mich wofür man new braucht.
    Ich weiß dass es sinnvoll ist Speicher dynamisch zu allokieren, [...]

    Alter, fällt dir nicht auf, dass sich das beißt?



  • Hallo Ravend und willkommen im Forum 🙂

    Ravend schrieb:

    Ich frage mich wofür man new braucht.
    Ich weiß dass es sinnvoll ist Speicher dynamisch zu allokieren, aber vor welche Zeiger muss ich new schreiben. Ich meine ein Zeiger zeigt nur auf ein Element.
    Es handelt sich ja nicht um eine variable Größe die noch nicht bekannt ist.

    Ich kenne mit meinen bescheidenen C++ Kenntnissen lediglich die alte Motivation einen Array zu erstellen, dessen Anzahl an Elementen erst zur Laufzeit bekannt sind, wie z.B. hier

    #include <iostream>
    
    int main()
    {
    	unsigned int const elements = 10;
    
    	double* p = new double [elements];
    
    	delete [] p;
    
    	return 0;
    }
    

    In Zeile 5 kann die Zahl 10 z.B. als Ausgabe einer anderen Funktion erfolgen. Dies lässt sich aber mit vector umgehen:

    #include <iostream>
    #include <vector>
    
    int main()
    {
    	unsigned int elements = 10;
    
    	// vector mit 'elements' Elementen als 0.0 initialisieren
    	std::vector<double> vec(elements, 0.0);
    
    	return 0;
    }
    

    Zeile 9 enthält alles was du benötigst, d.h. du musst nicht am Ende des Programms hinter dem Vektor aufräumen.

    Ansonsten müsstest du mal dein konkretes Problem posten wo du glaubst, dass du new benötigst. 🙂

    Viele Grüße,
    -- Klaus.



  • Klaus82 schrieb:

    Hallo Ravend und willkommen im Forum 🙂

    Ravend schrieb:

    Ich frage mich wofür man new braucht.
    Ich weiß dass es sinnvoll ist Speicher dynamisch zu allokieren, aber vor welche Zeiger muss ich new schreiben. Ich meine ein Zeiger zeigt nur auf ein Element.
    Es handelt sich ja nicht um eine variable Größe die noch nicht bekannt ist.

    Ich kenne mit meinen bescheidenen C++ Kenntnissen lediglich die alte Motivation einen Array zu erstellen, dessen Anzahl an Elementen erst zur Laufzeit bekannt sind, wie z.B. hier

    #include <iostream>
    
    int main()
    {
    	unsigned int const elements = 10;
    
    	double* p = new double [elements];
    
    	delete p;
    	
    	return 0;
    }
    

    In Zeile 5 kann die Zahl 10 z.B. als Ausgabe einer anderen Funktion erfolgen. Dies lässt sich aber mit vector umgehen:

    #include <iostream>
    #include <vector>
    
    int main()
    {
    	unsigned int elements = 10;
    
    	// vector mit 'elements' Elementen als 0.0 initialisieren
    	std::vector<double> vec(elements, 0.0);
    
    	return 0;
    }
    

    Zeile 9 enthält alles was du benötigst, d.h. du musst nicht am Ende des Programms hinter dem Vektor aufräumen.

    Ansonsten müsstest du mal dein konkretes Problem posten wo du glaubst, dass du new benötigst. 🙂

    Viele Grüße,
    -- Klaus.

    Zu jedem new[] gehört auch ein delete[] - du hast also ein Speicherleak in deinem Code!

    Ansonsten kann new auch dann Sinn machen, wenn man mit Polymorphie arbeitet, etc.



  • jkljkljkl schrieb:

    Zu jedem new[] gehört auch ein delete[] - du hast also ein Speicherleak in deinem Code!

    Danke, habe es editiert.

    Interessant, ich habe es ohne die eckigen Klammern durch valgrind gejagt und angeblich ist der heap wieder frei, er gibt mir lediglich einen Error aus. Erst wenn ich die eckige Klammer einsetze, dann verschwindet der Error.

    ==10981== HEAP SUMMARY:
    ==10981==     in use at exit: 0 bytes in 0 blocks
    ==10981==   total heap usage: 1 allocs, 1 frees, 80 bytes allocated
    ==10981== 
    ==10981== All heap blocks were freed -- no leaks are possible
    ==10981== 
    ==10981== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 27 from 6)
    ==10981== 
    ==10981== 1 errors in context 1 of 1:
    ==10981== Mismatched free() / delete / delete []
    ==10981==    at 0x402719C: operator delete(void*) (vg_replace_malloc.c:457)
    ==10981==    by 0x8048B38: main (in /home/<user>/Uni/Cpp/sandkasten/mb)
    ==10981==  Address 0x458f028 is 0 bytes inside a block of size 80 alloc'd
    ==10981==    at 0x40278F4: operator new[](unsigned int) (vg_replace_malloc.c:343)
    ==10981==    by 0x8048B28: main (in /home/<user>/Uni/Cpp/sandkasten/mb)
    ==10981== 
    --10981-- 
    --10981-- used_suppression:     27 U1004-ARM-_dl_relocate_object
    ==10981== 
    ==10981== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 27 from 6)
    

    Gruß,
    -- Klaus.



  • jkljkljkl schrieb:

    Ansonsten kann new auch dann Sinn machen, wenn man mit Polymorphie arbeitet, etc.

    Versteh ich nicht. Kannst du das erläutern?


Anmelden zum Antworten