die string-Klasse Zuweisungsoperator überladen in c++
Definierte ich meine eigene string-Klasse MyString. Alles funktioniert gut, bis ich weisen Sie einem Objekt zum anderen durch den überladenen operator=. Ich weiß, wo das problem ist, aber ich weiß nicht, wie es zu lösen ist. Jeder hilft?
class MyString{
public:
MyString( const MyString *strIni );
MyString( const char *str);
~MyString();
MyString& operator=( const MyString &str );
private:
char *str;
}
MyString::MyString( const MyString *strIni ){
this->str = new char[strlen(strIni->str)+1];
strcpy(this->str,strIni->str) ;
};
MyString::MyString( const char *str){
this->str = new char[ strlen(str) + 1 ];
strcpy(this->str , str);
};
MyString::~MyString(){
delete [] this->str ;
cout << "successfully deleted..." << endl;
};
MyString& MyString::operator=( const MyString &str ){
//temp obj holding the rhs
MyString strTmp(str);
//temp char pointer holding the rhs
char *cTmp = strTmp.str;
//temp obj holding this, later release this memory
strTmp.str = this->str ;
//this holding rhs; assignment done.
this->str = cTmp;
return *this ;
};
int main(){
{ //line 1
MyString mystr1("string #1"); //line 2
MyString mystr2("string #2"); //line 3
mystr1 = mystr2; //line 4
} //line 5
return 0;
}
Das problem, der code ist: auf line4, nach der Abtretung ist der Zeiger in beiden Objekten mystr1 mystr2 und beide zeigen die gleiche Zeichenkette "string #2". Wenn das Programm springen aus den Klammern in Zeile 5, die Destruktoren werden automatisch aufgerufen, durch Reihenfolge: mystr2 und dann mystr1. Nach mystr2 ist zerstört, die Erinnerung an "string #2" ist veröffentlicht worden. Wenn der Destruktor mystr1 versucht zu release nicht vorhandenen Speicher, das Programm ist abgestürzt.
Jemand kann mir helfen zu beheben der überlastung member-Funktion. Wenn ich diesen mystr1 = mystr2 Erzeuge ich einen neuen string, anstatt die zwei Zeiger weisen den gleichen string.
Vielen Dank!!
Updates für weitere Fragen......
danke Tonnen!!
eigentlich bin ich mit copy-and-swap in die überladen-Funktion. basierend auf dem @Mateusz Kołodziejski 's Beratung, habe ich es geändert:
MyString& MyString::operator=( const MyString &rhs ){
if( this != &rhs ){
//copy using constructor
MyString strTmp(rhs) ;
//swap
char *cTmp = strTmp.str;
//strTmp will be destructed, thus the memory in this will be released
strTmp.str = this->str ;
//size of rhs
const int str_size = strlen(rhs.str);
this->str = new char[str_size+1];
copy(rhs.str,rhs.str+str_size,this->str);
}
return *this ;
};
wenn die Destruktoren aufgerufen werden, kein Absturz. Aber wenn ein Ausdruck member-Funktion Hinzugefügt wird, scheint es ein weiteres problem:
void MyString::printout(){
int str_size = strlen(this->str);
cout << "string size: " << str_size << endl ;
for( int i=0;i<str_size;i++ ){
cout << *(this->str + i);
}
}
in der main-Funktion:
int main(){
{
MyString mystr1("string #1");
MyString mystr2("string #2");
mystr1.printout();
mystr2.printout();
mystr1 = mystr2;
cout << "after assignment: " << endl;
mystr1.printout();
mystr2.printout();
}
return 0;
}
sind die Ergebnisse:
string #1
string #2
after assignment...
string #2═²²²²
string #2
scheint, dass mystr1 ist nicht normal...
jemand erklären kann, für mich?
Danke Tonnen!!
- möglich, Duplikat der Kann eine lokale variable den Speicher zugegriffen werden, die außerhalb Ihrer Reichweite?
- Ich hoffe, dies ist für eine Schule-Zuordnung oder ähnlich, wie
std::string
schon gut genug. - Verwenden
MyString& MyString::operator=( const MyString &rhs ){
statt. Zu vielestr
s bezeichnen verschiedene Dinge. Vielleicht wird dann das problem klarer. - Auch, kopieren und tauschen.
- Nicht die Neugestaltung des Rad? Diese Art von bug ist, warum sollten Sie verwenden bereits vorhandene, gut dokumentierte und getestete Klassen. In diesem Fall
std::string
. Sie möglicherweise wollen untersuchenstrdup
duplizieren Sie die Zeichenfolge in Ihre Zuweisungsoperator obwohl. - Ja ich habe gerade realisiert, und das ist das problem und ich habe eine Antwort für Sie.
- Stick std::string und schaffen Bequemlichkeit die kostenlosen Funktionen. Somit haben Sie eine größere chance, um die Kompatibilität mit 3rd-party-software usw. Sie können auch darauf Vertrauen, dass es dort keine Fehler gibt in der string-Klasse, die Sie verwenden.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Haben Sie offensichtlich eine Korrektur der operator= () - Implementierung.
1) Verwenden Sie "RS" (Rechte Seite) statt "str" für den Variablen-Namen, um Mehrdeutigkeiten zu vermeiden.
2) überprüfen Sie Immer, wenn Ihr Objekt nicht zugewiesen wird, selbst.
3) lassen Sie die alten Speicher zugewiesen, vor der Zuweisung von neuen.
4) Kopieren Sie den Inhalt des RS zu dieser->str, anstatt nur umleiten Zeiger.
EDIT:
Hinzugefügt this->str = NULL; zur Vermeidung einer Doppel-deletion auf die mögliche Ausnahme von neuen, und später Objekt der Dekonstruktion.
Dies ist eine naive Implementierung - Sie müssen sich bewusst sein, das neue kann eine exception werfen. Kopieren-swap-idiom besser wäre hier wie vorgeschlagen von @nyarlathotep und hier beschrieben: Copy-and-swap.
this->str
noch Punkte, um nicht zugeordneten Speicherplatz (der Speicher gelöscht wird, bevor). Das ist der Grund, warum die swap-idiom wäre hier vorzuziehen.str
würde gelöscht, ein zweites mal...Hier das problem, dass mit der Erklärung
in der Zuweisungsoperator, rufen Sie die Standard-implizit generierte copy-Konstruktor. Und dass der Konstruktor wird einfach nur kopieren Sie die Zeiger, nicht erstellen Sie einen neuen Zeiger und kopieren Sie den Inhalt des string.
Des Konstruktors müssen Sie die Einnahme einer
MyString
Zeiger nicht ein copy-Konstruktor, einen copy-Konstruktor wäre eine Konstante Referenz statt. Wenn Sie ändern den Konstruktor der Einnahme einen Zeiger aufMyString
zu nehmen, ein Verweis statt, dann wird es besser funktionieren.char*
aus dem temp-Objekt, das anschließend gelöscht zu bekommen, richtig?this->str
dass gelöscht wird.std::swap
für bessere Lesbarkeit 😉