2015-08-27 10 views
5

Code wie folgt aus einem meiner Bücher zum Beispiel:Warum muss ich Ressourcen löschen, wenn ich den Operator "copy-assign" verwende?

class HasPtr { 
public: 
    HasPtr(const HasPtr& h): ps(new std::string(*h.ps)), i(h.i) { } 
    HasPtr(const std::string &s = std::string()): ps(new std::string(s)), i(0) { } 
    HasPtr& operator=(const HasPtr&); 
    ~HasPtr() { delete ps; } 
private: 
    std::string *ps; 
    int i; 
}; 

HasPtr& HasPtr::operator=(const HasPtr &rhs){ 
    auto newp = new string(*rhs.ps); // copy the underlying string 
    delete ps; // free the old memory 
    ps = newp; // copy data from rhs into this object 
    i = rhs.i; 
    return *this; // return this object 
} 

Scheint wie das Innere des Operators = könnte nur sein:

*ps = *rhs.ps 
i = rhs.i 
return *this; 

ohne die Notwendigkeit, den Zeiger zunächst zu löschen, scheint überflüssig um es zu tun. Es hat erwähnt, dass es in einer Weise geschrieben ist, das Objekt in einem geeigneten Zustand zu belassen, sollte eine Ausnahme auftreten, aber nicht darüber bekannt gegeben haben, aber ich sehe nicht, welche Ausnahme auftreten könnte, die selbst meine Alternative nicht behandeln würde. Warum muss das Objekt zuerst gelöscht werden, bevor es zugewiesen wird?

+3

Sie müssen die [Regeldetri] (http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) (wobei beachten wird trivial beobachtet, indem man der [Null-Regel] folgt (http://stackoverflow.com/q/22806523/315052)). Verwenden Sie auch [copy-and-swap] (http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom), wenn Sie einen eigenen Zuweisungsoperator implementieren. – jxh

+0

Welches Buch? –

+1

@LightnessRacesinOrbit C++ Primer 5. Auflage, Kapitel 13.2.1 – AntiElephant

Antwort

4

Das sieht mir gut.

Und Sie haben Recht, std::string Zuweisung already bietet eine starke Ausnahme Garantie, so dass Sie das Objekt immer noch in seinem ursprünglichen Zustand verlassen, sollte eine Ausnahme beim Kopieren der Zeichenfolge auftreten.

Natürlich gibt es keinen Grund, eine std::string mit new so zuzuteilen. Man könnte dies nur stattdessen schreiben:

class HasNoPtr { 
public: 
    HasNoPtr(const std::string& s): ps(s), i(0) { } 
private: 
    std::string ps; 
    int i; 
}; 
5

In diesem Fall, ja, das wäre schön.

Sie sind nicht undicht die dynamisch zugewiesenen String: Sie es erneut verwenden.