Problem beim erstellen eines Objekts mit new



  • Hallo alle zusammen,

    ich habe Schwierigkeiten mit einem programm, das ein Objekt mittels new operator auf dem Heap speicher erstellen soll

    #include <iostream>
    
    using namespace std;
    
    class TestKlasse
    {
    	public:
    	int * test;
    	TestKlasse();
    };
    
    TestKlasse::TestKlasse()
    {
    	* test = 6;
    }
    
        int main()
        {
        		TestKlasse * test = new TestKlasse;
        		cout << *test->test; 
        }
    

    Das Programm stürzt immer ab, was mache ich falsch??? 😕



  • Du hast für deine Variable(Zeiger) int *test keinen Speicher reserviert. Er zeigt somit irgendwohin und löst somit mit hoher Wahrscheinlichkeit einen crash aus.



  • Es geht auch, wenn man die testVar einfach so in der klasse definiert

    #include <iostream>
    
    using namespace std;
    
    class TestKlasse
    {
    	public:
    	int testVar;
    	TestKlasse();
    };
    
    TestKlasse::TestKlasse()
    {
    	testVar = 6;
    }
    
        int main()
        {
        		TestKlasse * test = new TestKlasse;
        		cout << test->testVar;
        }
    

    Befindet sich die testVar jetzt im Heap oder Stack? 😕



  • wasd schrieb:

    Befindet sich die testVar jetzt im Heap oder Stack? 😕

    Genau genommen weder noch, testVar liegt auf dem Freestore (durch new oder new[] angefordert). Auf dem Heap wäre durch malloc() und Konsorten allokiert. Und natürlich geht es hier nur um die Variable testVar dieses mit new konstruierten Objekts, testVar s anderer Instanzen können in einem anderen Speicherbereich liegen.

    wasd schrieb:

    Es geht auch, wenn man die testVar einfach so in der klasse definiert

    Es geht auch, wenn test selbst automatisch statt dynamisch angelegt wird. Generell ist dieses Vorgehen empfohlen, vermeide unnötige manuelle Speicherverwaltung. Und wenn du sie verwendest, gib den Speicher mit delete bzw. delete[] frei.



  • 2late



  • Nexus schrieb:

    wasd schrieb:

    Befindet sich die testVar jetzt im Heap oder Stack? 😕

    Genau genommen weder noch, testVar liegt auf dem Freestore (durch new oder new[] angefordert). Auf dem Heap wäre durch malloc() und Konsorten allokiert. Und natürlich geht es hier nur um die Variable testVar dieses mit new konstruierten Objekts, testVar s anderer Instanzen können in einem anderen Speicherbereich liegen.

    wasd schrieb:

    Es geht auch, wenn man die testVar einfach so in der klasse definiert

    Es geht auch, wenn test selbst automatisch statt dynamisch angelegt wird. Generell ist dieses Vorgehen empfohlen, vermeide unnötige manuelle Speicherverwaltung. Und wenn du sie verwendest, gib den Speicher mit delete bzw. delete[] frei.

    Bin jetzt ein bisschen verwirrt.. dachte ein objekt muss immer mit new() erstellt werden (kann auch sein das das nur bei java so ist), weil eine Variable doch nur ein primitiver Datentyp (int, short usw) oder eine Referenz auf ein Objekt sein kann.

    ansonsten müsste ja bei jeder Zuweisung das gesamte Objekt kopiert werden..

    TestKlasse test;
    TestKlasse test1;
    test = test1;
    


  • Ist halt so geht auch ohne new in C++. Dies sind dann aber lokale Objekte die mit dem Ende des Scopes vernichtet werden. Zugriff über den .-operator.

    Folgendes darfst du machen:

    Obj a; //Objekt erstellen
    Obj *p = &a; //Zeiger der auf lokales Objekt zeigt
    
    //Zugriffe auf Funktionen
    a.foo();
    p->foo();
    
    //Mit ende des Scopes darf p nicht mehr verwendet werden, da Objekt zerstört wurde
    
    Obj *a = new Obj; //Zeiger der auf Heap-Objekt zeigt
    
    a->foo(); //Zugriff auf Funktion
    
    delete a; //Zerstören des Objektes a darf nicht mehr verwendet werden
    

    Edit: In C++ vermeidet man das Verwenden von (rohen) Pointern und verwendet Container und Smart-Pointer, die automatisch Speicher reservieren und wieder freigeben.



  • wasd schrieb:

    Bin jetzt ein bisschen verwirrt.. dachte ein objekt muss immer mit new() erstellt werden (kann auch sein das das nur bei java so ist), weil eine Variable doch nur ein primitiver Datentyp (int, short usw) oder eine Referenz auf ein Objekt sein kann.

    Ja, das ist Java. In C++ sind die Unterschiede zwischen primitiven Datentypen und Klassen klein. Es gibt manuelle und automatische Speicherverwaltung (hat nicht direkt mit Stack vs. Freestore zu tun), wobei letztere fast immer zu bevorzugen ist, weil einfacher, sicherer, weniger fehleranfällig. Stichwort RAII.

    wasd schrieb:

    ansonsten müsste ja bei jeder Zuweisung das gesamte Objekt kopiert werden..

    Richtig, aber mit einer Zuweisung willst du das ja gerade. Willst du nur einen Verweis, erstellst du eben einen Zeiger oder eine Referenz auf das Objekt.



  • Okay danke habs verstanden. mal ne andere Frage: Hab gelesen dass inline klassenmethoden schneller verarbeitet werden als die normalen. kann ich dann nicht einfach alle methoden Inline machen, sofern die größe der datei keine rolle spielt??



  • wasd schrieb:

    Okay danke habs verstanden. mal ne andere Frage: Hab gelesen dass inline klassenmethoden schneller verarbeitet werden als die normalen.

    Kann man gar nicht mehr allgemein so sagen. Manchmal ist outline auch schneller, wegen Cache-Lokalität. Der Compiler macht automatisch die inline, die er für würdig hält, und kann die Funktionen schon verflixt gut einschätzen.



  • Ahh okay, eine Frage hab ich noch 😃

    Hab schon öfters gesehen, das char* pointer für Zeichenketten benutzt werden.

    in diesem Beispiel zeigt der pointer ja auf das erste byte des Strings, also das "T".

    char *t;
    t = "Test!";
    
    cout << t;
    

    Ich versteh nicht, wie das Programm funktionieren kann, da erstens bei der initialisierung der * vor dem t fehlt und die Ausgabe dann doch eigentlich die Adresse sein müsste?

    und zweitens woher weiß das Programm bei cout << t die Länge des Strings?



  • Erstens muss es

    const char* t = "blubb";
    

    heißen.
    Zweitens hat jedes string-Literal eine Adresse, auch wenn das zuerst komisch erscheint. Der string liegt aber in einem Read-Only bereich, du darfst da also nichts ändern.

    C-Strings sind 0-terminiert, das heißt, der string hat am Ende immer eine 0, nicht '0' oder "0" sondern 0. Die Länge des String "muh" ist damit 4.



  • Der Code funktioniert garnicht (undefiniertes Verhalten) Der Pointer zeigt auf irgendeine Adresse. Es wurde weder eine gültige Adresse auf dem Stack angegeben ) noch Speicher auf dem Heap für den String reserviert. Wie ich in meinem Post vorher schon erläutert habe.

    Ein String wird immer mit '\0' abgeschlossen. somit hat ein char array[6] auch nur maximal 5 Zeichen, da das Sechste für die Nullterminierung benötigt wird. Strings in Anführungszeichen angegeben haben eine Nullterminierung.



  • HighLigerBiMBam schrieb:

    Der Code funktioniert garnicht (undefiniertes Verhalten) Der Pointer zeigt auf irgendeine Adresse. Es wurde weder eine gültige Adresse auf dem Stack angegeben ) noch Speicher auf dem Heap für den String reserviert. Wie ich in meinem Post vorher schon erläutert habe.

    Bei mir gehts schon die ausgabe ist "Test!"

    soweit ich weiß ist

    char* t = "blubb";
    

    die verkürzte version von

    char *t;
    	t = "blubb";
    


  • Nein, die richtige 🤡



  • 314159265358979 schrieb:

    Nein, die richtige 🤡

    okay und was ist an der anderen falsch??



  • Das const fehlt.



  • 314159265358979 schrieb:

    Das const fehlt.

    vielleicht sollte meine Variable auch gar keine Konstanste sein? 😃



  • Wenn du den string so zuweist, MUSS sie const sein.



  • wasd schrieb:

    Ich versteh nicht, wie das Programm funktionieren kann, da erstens bei der initialisierung der * vor dem t fehlt und die Ausgabe dann doch eigentlich die Adresse sein müsste?

    Du weist die Adresse des Stringliterals dem char -Zeiger zu. Die Ausgabe funktioniert, weil der Stream-Operator für char* überladen ist.

    wasd schrieb:

    vielleicht sollte meine Variable auch gar keine Konstanste sein?

    Ist sie so oder so nicht. Aber der Zeiger soll auf const zeigen. "Der string liegt aber in einem Read-Only bereich, du darfst da also nichts ändern." Daher ist bei Stringliteralen nur const char* sinnvoll.

    Wo liegt dein momentanes Problem?


Anmelden zum Antworten