std::string als Stackobjekt in Klasse - problemlos?



  • Ist richtig so.

    Faustregel: Pro new ein delete. Pro new[] ein delete[].



  • Janjan schrieb:

    Faustregel: Pro new ein delete. Pro new[] ein delete[].

    Bekannteste Abweichung von der Regel: Smart Pointer.

    @theliquidwave

    Dekonstruktor

    Destruktor!

    Und hast du denn das Programm nicht getestet?! - Da hättest du gesehen, dass genau diese Reihenfolge ausgegeben wird.. (oder wolltest du nur wissen, ob das so auch definiert ist?)



  • theliquidwave schrieb:

    class CTest /*Warum immer C davor? Ungarische Notation ist recht veraltet...*/
    {
    public:
    	CTest(void) // F ist die void-Angabe eigentlich Standardkonform?
                        /* Sie ist erlaubt. Aber unnötig. Eigentlich nur ein
                           C-Relikt, dort wars obligatorisch */
    	{
    		this->m_strText = "standard"; // gibt es eine andere Möglichkeit, das zu setzen, außer im Konstruktor?
                    /* Jein, da gehört eigentlich in die Initialisierungsliste.
                       Und ja, du kannst den Wert in jeder Methode ändern, da er
                       nicht const ist. 
                       Das ständige this-> vorneweg ist übrigens nicht nötig,
                       seltene Spezialfälle mal ausgenommen.  
                       Das m_ am Variablennamen grenzt wieder an ungarische
                       Notation, ist aber Geschmackssache.*/
    	}
    	
    	~CTest(void)
    	{
    		// muss ich hier was aufräumen?
                    /* nein. Destruktoren von Membern werden automatisch 
                       aufgeräumt, std::string verwaltet seinen Soecher selbst
                       und sorg für dessen Freigabe. */
    	}
    	
    	std::string receive(void)
    	{
    		return this->m_strText; // hier entsteht eine Kopie auf dem Stack, also kein Memoryleak oder?
                    /* richtig, es wird ein temporäres Objekt erzeugt. */
    	}
    	
    	void change(std::string strNew)
    	{
    		this->m_strText = strNew;
                    /* zum this-> siehe oben. 
                       strNew ist hier eine lokale Kopie, die nur 
                       einmal gelesen wird für die Zuweisung. Eine 
                       konstante Referenz hätte es hier auch getan. */
    
    	}
    
    private:
    	std::string m_strText;
    };
    
    void test()
    {
    	CTest *pTest = new CTest;
    	pTest->change("omg");
    	std::string strTest = pTest->receive(); // Kopie auf Stack, richtig?
                             /* Ja... */
    	strTest = "bla"; // nur diese Kopie, also nicht der String in der Klasseninstanz selbst, wird verändern, richtig?
                             /* Ja, weils eine Kopie ist, also ein anderes 
                                Objekt und keine Referenz auf das string-Objekt
                                hinter pTest */
    	delete pTest;    /* Das new und delete ist unnötig. Du hättest dein
                                CTest-Objekt auch gleich auf dem Stack anlegen
                                können. Hat nur Vorteile in diesem Fall. */
    }
    

    Du scheinst von irgendeiner anderen Programmiersprache zu stammen, zumindest lassen dein new/delete und die ganzen Fragen nach den automatischen Destruktor-Aufrufen usw. darauf schließen. Ein gutes C++-Buch sollte da Abhilfe schaffen. Das wichtigste dabei: vergiss was du in der anderen Sprache gelernt hast. Solche Dinge lassen sich meist nicht ohne weiteres von einer Sprache auf die andere übertragen.



  • blub² schrieb:

    Ja.

    Jeweils im Konstruktor bzw. Destruktor der Klasse in der das Objekt liegt beim zerstören des Objekts.

    Gut :>

    drakon schrieb:

    Destruktor!

    Danke 🤡

    drakon schrieb:

    Und hast du denn das Programm nicht getestet?! - Da hättest du gesehen, dass genau diese Reihenfolge ausgegeben wird.. (oder wolltest du nur wissen, ob das so auch definiert ist?)

    Ich wollte wissen wie es im Standard definiert ist. Ich habe zu viel gesehen um zu glauben, dass es auch im GCC so aussieht wie mit dem MSVC...

    pumuckl schrieb:

    Warum immer C davor? Ungarische Notation ist recht veraltet...

    Keine Ahnung... Ich habe es mal in einem Tutorial gesehen, und auch in einigen Sourcecodes. Ich fand es praktisch. Aber stimmt, durch die heutigen IDEs ist es eigentlich nicht mehr nötig.

    pumuckl schrieb:

    // F ist die void-Angabe eigentlich Standardkonform?
    Sie ist erlaubt. Aber unnötig. Eigentlich nur ein
    C-Relikt, dort wars obligatorisch

    Ok, ich habe echt kein Plan wo ich das her hab.

    pumuckl schrieb:

    Jein, da gehört eigentlich in die Initialisierungsliste.
    Und ja, du kannst den Wert in jeder Methode ändern, da er nicht const ist.

    Gut 🙂

    pumuckl schrieb:

    Das ständige this-> vorneweg ist übrigens nicht nötig,
    seltene Spezialfälle mal ausgenommen.
    Das m_ am Variablennamen grenzt wieder an ungarische
    Notation, ist aber Geschmackssache.

    So finde ich es übersichtlicher. Aber eins von beiden würde sicher reichen.

    pumuckl schrieb:

    strNew ist hier eine lokale Kopie, die nur
    einmal gelesen wird für die Zuweisung. Eine
    konstante Referenz hätte es hier auch getan.

    Also so, und es wäre trotzdem eine Kopie in m_strText?

    void change(const std::string &strNew)
    {
        this->m_strText = strNew;
    }
    

    pumuckl schrieb:

    Das new und delete ist unnötig. Du hättest dein
    CTest-Objekt auch gleich auf dem Stack anlegen können. Hat nur Vorteile in diesem Fall.

    Jo, war auch nur ein Beispiel auf mein speziellen Anwendungsfall bezogen. Hätte ich vielleicht dazuschreiben können.

    pumuckl schrieb:

    Du scheinst von irgendeiner anderen Programmiersprache zu stammen, zumindest lassen dein new/delete und die ganzen Fragen nach den automatischen Destruktor-Aufrufen usw. darauf schließen.

    Ich komme aus der Welt voller GCs.

    pumuckl schrieb:

    Ein gutes C++-Buch sollte da Abhilfe schaffen. Das wichtigste dabei: vergiss was du in der anderen Sprache gelernt hast.

    Guter Tipp - ich schleppe wohl wirklich ein paar "Altlasten" mit mir herum.

    Danke an alle!!!



  • theliquidwave schrieb:

    pumuckl schrieb:

    Ein gutes C++-Buch sollte da Abhilfe schaffen. Das wichtigste dabei: vergiss was du in der anderen Sprache gelernt hast.

    Guter Tipp - ich schleppe wohl wirklich ein paar "Altlasten" mit mir herum.

    In einem solchem Fall ist imo "The C++ programming language" sehr geeignet. Ist ein rechtes Buch, aber wenn du schon Erfahrung hast, dann kannst du da enorm profitieren und erhälst einen guten Einblick, wie alles in C++ läuft.



  • Danke. Das werde ich mir mal anschauen 🙂
    Eine Frage habe ich aber noch... Es ist nicht möglich, das gleiche wie oben zu machen, wenn die Klasse einen Konstruktor hat, der einen oder mehrere Parameter hat, oder?

    Gruß



  • Ich verstehe nicht ganz. Was meinst du genau? Beispiel?



  • class CBla
    {
    public:
        CBla(); // dieser wird dann ja wohl aufgerufen
        CBla(std::string strBla);
        CBla(int X);
    };
    
    class CHolder
    {
    private:
        CBla m_Bla; // ist es irgendwie möglich, dass der 2. oder 3. Konstruktor, und nicht der erste aufgerufen wird?
    }
    

    Gruß



  • Jap. Klar geht das. Dann musst du einfach die Initialisierungsliste benutzen.

    class CHolder
    {
    private:
        CBla m_Bla;
     CHolder ()
       :
     m_Bla ( 2 ) // oder m_Bla ( "blub" )
     {}
    }
    


  • Cool 😃
    Danke!



  • theliquidwave schrieb:

    pumuckl schrieb:

    strNew ist hier eine lokale Kopie, die nur
    einmal gelesen wird für die Zuweisung. Eine
    konstante Referenz hätte es hier auch getan.

    Also so, und es wäre trotzdem eine Kopie in m_strText?

    void change(const std::string &strNew)
    {
        this->m_strText = strNew;
    }
    

    Ich wollte mal pushen...
    Wann genau soll ich eine Referenz benutzen?
    Landet in m_strText trotzdem noch eine Kopie, die ich dann unabhängig vom echten strNew verändern kann? Ist strNew selbst die Kopie, oder wird der String erst beim operator= kopiert?

    Gruß



  • Eine const-Referenz kannst du eigentlich immer verwenden.

    m_strText erhält durch das = eine Kopie.
    strNew ist nicht die kopie, durch die Übergabe per Referenz hast du dafür gesagt, das der Parameter nicht kopiert wird.



  • OK. Danke!

    Gruß


Anmelden zum Antworten