Beinhaltet List-Container Objekte oder Referenzen?



  • Hallo Jester,

    die Fehlermeldung findest du in meinem letzten Beitrag. Vielleicht hilft es, wenn ich noch Copy-Konstruktor und Zuweisungsfunktion der myDynamicClass Klasse poste:

    MyDynamicClass &MyDynamicClass::operator=(MyDynamicClass &newMyDynamicClass)
    {
       cout << "Zuweisung MyDynamicClass" << endl << flush;
    
       // is new object the same object?
       if(this != &newMyDynamicClass)
       {
          // free memory
          if(m_puiData != NULL)
          {
             delete [] m_puiData;
          }
    
          // copy data
          m_uiStartAddress = newMyDynamicClass.m_uiStartAddress;
          m_uiLength = newMyDynamicClass.m_uiLength;
    
          m_puiData = new uint16_t[m_uiLength];
    
       	for(uint16_t uiDummy = 0; uiDummy < m_uiLength; ++uiDummy)
       	{
       		m_puiData[uiDummy] = newMyDynamicClass.m_puiData[uiDummy];
       	}          
       }
    
       return *this;
    }
    
    MyDynamicClass::MyDynamicClass(const MyDynamicClass &newMyDynamicClass)
    {
    	// copy data
    	m_uiStartAddress = newMyDynamicClass.m_uiStartAddress;
    	m_uiLength = newMyDynamicClass.m_uiLength;
    
    	m_puiData = new uint16_t[m_uiLength];
    
    	for(uint16_t uiDummy = 0; uiDummy < m_uiLength; ++uiDummy)
    	{
    		m_puiData[uiDummy] = newMyDynamicClass.m_puiData[uiDummy];
    	} 	
    }
    


  • Ich würde dir raten, den Zuweisungsoperator über den CopyCtor zu implementieren (spart Schreibarbeit, nutze swap) und bei beiden den Parameter als const Referenz zu übernehmen.
    Das flush nach dem endl ist auch zuviel. endl mach schon selbst ein flush.



  • Danke für die Tipps. Funktioniert jetzt auch.

    Meintest du so?:

    MyDynamicClass &MyDynamicClass::operator=(const MyDynamicClass &newMyDynamicClass)
    {
       cout << "Zuweisung MyDynamicClass" << endl;
    
       // is new object the same object?
       if(this != &newMyDynamicClass)
       {
          // free memory
          if(m_puiData != NULL)
          {
             delete [] m_puiData;
          }
    
          // copy data
          MyDynamicClass(newMyDynamicClass);       
       }
    
       return *this;
    }
    

    Gruß
    Gustav



  • Nein, das funktioniert nicht. Da wo Du vermeintlich den Copy-Konstruktor verwendest erstellst Du nur ein temporäres Objekt. Gemeint war:

    MyDynamicClass const& operator=(MyDynamicClass const& other)
    {
      MyDynamicClass tmp(other);
      tmp.swap(*this);
      return *this;
    }
    


  • EDIT: jetzt überflüssig.



  • Jester schrieb:

    Nein, das funktioniert nicht. Da wo Du vermeintlich den Copy-Konstruktor verwendest erstellst Du nur ein temporäres Objekt. Gemeint war:

    MyDynamicClass const& operator=(MyDynamicClass const& other)
    {
      MyDynamicClass tmp(other);
      tmp.swap(*this);
      return *this;
    }
    

    ich müsste also lediglich eine swap funktion implementieren mit folgendem code:

    std::swap(m_uiStartAddress, src.m_uiStartAddress);
    	std::swap(m_puiData, src.m_puiData);
    	std::swap(m_uiLength, src.m_uiLength)
    

    (also alle Elemente tauschen)

    Seh ich richtig, dass somit beim = Operator kein delete mehr nötig ist, da die 2 Objekte getauscht werden und somit das ursprüngliche Objekt(this) zum temporären wird und dieses per Destruktor freigegeben wird?

    Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?

    Gruß
    Gustav



  • Gustav Hummel schrieb:

    ich müsste also lediglich eine swap funktion implementieren mit folgendem code:

    std::swap(m_uiStartAddress, src.m_uiStartAddress);
    	std::swap(m_puiData, src.m_puiData);
    	std::swap(m_uiLength, src.m_uiLength)
    

    (also alle Elemente tauschen)

    Ja genau.

    Seh ich richtig, dass somit beim = Operator kein delete mehr nötig ist, da die 2 Objekte getauscht werden und somit das ursprüngliche Objekt(this) zum temporären wird und dieses per Destruktor freigegeben wird?

    Ganz genau. Und das ist auch der große Vorteil davon: Es ist Exception-sicher. Stell Dir vor bei Deiner alten Version klappt zwar das freigeben, aber beim Speicher anfordern (oder Objekte kopieren) fliegt eine Exception. Dann sind Deine alte Daten weg und die neuen kriegste nicht konstruiert. Dein Zustand ist undefiniert. Hier ist es so, dass zunächst der Copy-Konstruktor alle gefährlichen Sachen macht. Fliegt dabei eine Exception ist Dein Objekt noch unverändert. Dann kommt swap, aber das macht nur ungefährliche Sachen, da kann nix fliegen (zumindest sollte man's so implementieren). Danach ist Dein Objekt im neuen Zustand.

    Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?

    Ich mach das immer so. Aber letztlich ist es egal. 🙂



  • Hi,

    Gustav Hummel schrieb:

    ...
    Achja hat es einen speziellen Grund, wieso du das const direkt vor & schreibst?...

    Also ich habe mir das auch angewöhnt, weil man dann mit komplizierteren "const"-trukten ( 😉 ) besser klarkommt.

    Ich merke mir immer "const wirkt rückwärts":

    char const * a; // Zeiger veränderbar, chars NICHT
    char * const b; // Zeiger NICHT veränderbar, chars schon
    char const * const c; // Zeiger NICHT veränderbar, chars auch NICHT
    ...
    const char * d; // aus historischen Gründen identisch mit char const *
    

    Spätenstens bei Funktionspointern wird es ziemlich schnell unübersichtlich, weswegen ich eine einheitliche Schriftweise bevorzuge.

    Gruß,

    Simon2.



  • Super. Wieder was gelernt. Danke allen Beteiligten. 👍

    Gruß
    Gustav



  • Gern geschehen ! 👍

    Gruß,

    Simon2.


Anmelden zum Antworten