Memory leak bei überladenen Operatoren verhindern



  • Hallo alle zusammen,

    ich will mal einige numerische Verfahren implementieren und bin dabei auf eine Frage gestoßen. Meine Klassendefinition sieht so aus:

    class Matrix {
        [...]
        Matrix& operator=(const Matrix& original);
        Matrix& operator+(const Matrix& summand);
        [...]
        int m_rows, m_cols;
    };
    
    [...]
    
    Matrix& Matrix::operator+(const Matrix& original) {
        Matrix* tmp = new Matrix(m_rows, m_cols);
        [...]
        return *tmp;
    }
    

    Das Problem ergibt sich dann, wenn ich sowas schreibe wie:

    Matrix a,b,c;
    c = a + b;
    

    Dann erzeugt a + b ja eine neue Instanz von Matrix, die nach der Zuweisung als verwaistes Objekt im Speicher liegt. (Wie) Kann man sowas elegant umgehen?

    Gruß Andreas



  • Kommst du zufällig von Java?

    In C++ müssen Objekte nämlich nicht mit new angelegt werden.

    Du kannst auch einfach schreiben:

    Matrix& Matrix::operator+(const Matrix& original) { 
        Matrix tmp(m_rows, m_cols); 
        [...] 
        return tmp; 
    }
    

    Auf Member wird dann per . anstatt -> zugegriffen.

    Ps:
    Außerdem solltest du keine Referenz zurückgeben, da die sonst auf ein gelöschtes Objekt zeigt, da der Scope der Funktion verlassen wurde.



  • Nicht Matrix& zurückgeben, sondern einfach Matrix.
    Copy- Constructor und Assignment- Operator muss implementiert sein.

    Edit: Nimm Dir doch als Bsp. std::complex<T>



  • Ja, ich komme tatsächlich von Java und habe noch nicht viel Erfahrung mit c++, aber bei solchen Projekten ist dann Operatorüberladung einfach deutlich von Vorteilen.
    Bei der Methode mit den Copy-Konstruktoren würde dann doch bei

    a = b + c * d;
    

    z.B für c * d und für b + c * d je eine Instanz erzeugt werden. Endet dann deren Scope am Ende der Zeile?

    Gruß Andreas

    PS: Danke für eure schnellen Antworten.



  • gurumusch schrieb:

    [...]Endet dann deren Scope am Ende der Zeile?

    Der Scope liegt zwischen den geschwungenen Klammern:

    {
        obj a;
        {
            obj b;
        }//b wird zerstört
    }//a wird zerstört
    


  • c++ besitzt tatsächlich harte scopes. im gegensatz zu java werden lokale objekte (ohne new erzeugt) sofort bei verlassen ihres scopes zerstört.



  • Danke für eure Hilfe. Also, jetzt sieht es dann so aus:

    class Matrix {
        [...]
        Matrix(const Matrix& original)
        Matrix operator=(const Matrix& original);
        Matrix operator+(const Matrix& summand);
        [...]
        int m_rows, m_cols;
    };
    
    [...]
    

    Ich schätze, ich werde werde c++ an der Stelle auch etwas besser verstehen, wenn ich es erstmal 2-3 mal debuggt habe.

    Gruß Andreas



  • Um die temporären Variablen und ihr Verhalten zu beobachten und verstehen könntest du im Kontruktor und Destruktor ein kurzes cout-statement einbauen - dann siehst du auch wie der Kompiler die temporären Objekte eventuell wegoptimiert..



  • Beim Assignement Operator sollte eine Referenz zurückgegeben werden.
    (Sorry, dass ich das nicht schon oben geschrieben habe.)

    // Dekl.
    Matrix& operator=(const Matrix& original);
    
    // Impl.
    Matrix& Matrix::operator=(const Matrix& original)
    {
       //
       // kopieren der Member...
       //
       return *this;
    }
    

    Bei den Überladungen +, -, *, / sollten Kopien zurückgegeben werden.


Anmelden zum Antworten