-5

私は人々が登録するためのプログラムを行っていますが、演算子 = のオーバーロードに問題があります。

class CRegister、 struct Person、およびPlace.

struct Places{
    char date[11];
    char * street;
    char * city;

Places & operator = (const Places & other){
        delete [] street;
        delete [] city;

        strncpy (date, other.date, 11);

        int len;
        len = strlen(other.street);
        this->street = new char[len];
        strncpy ( this->street, other.street, len );

        len = strlen(other.city);
        this->city = new char[len];
        strncpy ( this->city, other.city, len );

        return *this;
    }
}


struct Person{
    char id[12];
    char * name;
    char * surname;
    Places ** oldPlaces;

    int placesCount;
    int placesSize;
};

Person & Person::operator =(const Person& other){
    for (int i = 0; i < this->placesSize; i++){
         delete this->oldPlaces[i];
    }
    delete [] this->oldPlaces;
    delete [] name;
    delete [] surname;


    placesCount = other.placesCount;
    placesSize = other.placesSize;

    oldPlaces = new Places*[other.placesSize];

    strncpy (id, other.id, 11);

        int len;

        len = strlen(other.name);
        this->name = new char[len];
        strncpy ( this->name, other.name, len );

        len = strlen(other.surname);
        this->surname = new char[len];
        strncpy ( this->surname, other.surname, len );

    for (int i = 0; i < placesCount; i++){
        oldPlaces[i] = other.oldPlaces[i];
    }

    return *this;
}



class CRegister     
 {
   private:
    Person **persons;
    int personCount;
    int personSize;
 };

 CRegister& CRegister::operator =(const CRegister& other){
    for (int i = 0; i < this->personSize; i++){
        delete this->persons[i];
    }
    delete [] this->persons;

    personCount = other.personCount;
    personSize = other.personSize;

    persons = new Person*[other.personSize];

    for (int i = 0; i < personCount; i++){
        persons[i] = other.persons[i];
    }


    return *this; 
 }

ただし、コードはコンパイルされていますが、Netbeans は実行に失敗したことを示しています。なんで?

4

3 に答える 3

2
    len = strlen(other.city);
    this->city = new char[len];
    strncpy ( this->city, other.city, len );

これは文字列の長さを保持しません。後のコードはどのくらいの長さかをどのように知るのthis->cityでしょうか?

于 2013-04-12T15:59:47.943 に答える
1

あなたは3 つのルールに従っていません。唯一の理由ではないにしても、それはおそらく1つの理由かもしれません.

別の注意として、

于 2013-04-12T15:59:29.827 に答える
1

基本的に (クラスにラップされた) C を使用しているため、おそらく C コードで最も頻繁に発生するエラーを作成しました。 final を数えstrlen に、文字列内の文字数を返します。 finalをコピーするので、もう 1 文字使用すると(そうすべきではありません)、終了していない文字列になってしまい ます。したがって、ではバッファの最後をオーバーランし、では文字列を読み込もうとする人は誰でもバッファの最後をオーバーランします (それらは a まで続くため)。'\0'strcpy'\0'strncpy'\0'strcpystrncpy'\0'

strlen ルールは、戻り値よりも 1 つ多い文字を割り当てることです。

size_t len = strlen( other.name ) + 1;
name = new char[ len ];
strcpy( name, other.name );

(標準 C ではありませんが、多くのシステムにstrdupはこれを行う関数があります。mallocもちろん を使用するため、freeではなく で解放する必要がありdeleteます。)

それを超えて、前に言ったことを繰り返します。割り当てのいずれかが失敗した場合、コードはオブジェクトを一貫性のない状態のままにします。 クラス内の何かを変更する前に、失敗する可能性のあるすべてのことを常に実行してください。swap イディオムは の古典的なものですoperator=が、それ以外の場合は、ローカル ポインターを使用できます。

char* newName = NULL;
char* newSurname = NULL;
Places* newPlaces = NULL;

try {
    newName = strdup( other.name);
    newSurname = strdup( other.surname );
    newPlaces = deapCopyPlaces( other.places );
} catch ( ... ) {
    deepDelete( newPlaces );
    delete [] newName;
    delete [] newSurname;
}
//  And only now...
deepDelete( places );
delete [] name;
delete [] surname;
name = newName;
surname = newSurname;
places = newPlaces;

しかし、エラー処理コードをすべて複製する必要がなくなるため、swap イディオムの方がはるかに好ましいです。

于 2013-04-12T16:35:13.803 に答える