0

解決済み

解決策: コピー コンストラクターを提供し、3 つのルールに従います。

元の問題

インターバルのマトリックスであるクラスを実装しています。私のIntervallクラスは次のようになります(短縮):

class Intervall
{
friend std::ostream& operator<<(std::ostream& output, const Intervall& i);

public:
    Intervall();
    Intervall(double n);

private:
    double min_value;
    double max_value;
};

この実装では:

Intervall::Intervall(){
    min_value = 0;
    max_value = 0;
}

Intervall::Intervall(double n){
    min_value = n;
    max_value = n;
}

ostream& operator<<(ostream& output, const Intervall& i){
    output << "[" <<  i.min_value << ", " << i.max_value <<"]";
    return output;
}

私の Matrix クラスは次のようになります。

class IntervallRMatrix
{
friend std::ostream& operator<<(std::ostream& output, const IntervallRMatrix& irm);

public:
   IntervallRMatrix();
   ~IntervallRMatrix();

   void setIdentity();

   IntervallRMatrix clone();

private:
   void initialize();

   Intervall* data;
   Intervall** cells;
};

次の実装を使用します。

IntervallRMatrix::IntervallRMatrix(){
    initialize();
}

IntervallRMatrix::~IntervallRMatrix(){
    delete cells;
    delete data;
}

ostream& operator<<(ostream& output, const IntervallRMatrix& irm){
    output << "3 x 3" << endl;
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            output << irm.cells[i][j];
        }
        output << endl;
    }
    return output;
}

void IntervallRMatrix::setIdentity(){
    cells[0][0] = Intervall(1);
    cells[1][1] = Intervall(1);
    cells[2][2] = Intervall(1);
}

IntervallRMatrix IntervallRMatrix::clone(){
    IntervallRMatrix result;
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            result.cells[i][j] = cells[i][j];
        }
    }
    return result;
}

void IntervallRMatrix::initialize(){
    data = new Intervall[9];
    for(int i=0; i<9; i++){
        data[i] = Intervall();
    }
    cells = new Intervall*[3];
    for(int i=0; i<3; i++){
        cells[i] = &data[3*i];
    }
}

クローン機能を使用するまで、これはすべて正常に機能します。このコードは、メモリ エラーを生成します。

int main()
{
    IntervallRMatrix m1;
    m1.setIdentity();
    cout << "m1: " << m1 << endl;

    IntervallRMatrix m2 = m1.clone();
    cout << "m2: " << m2 << endl;
    return 0;
}

最初の cout は意図したとおりに機能します。2番目のカウトはそうではありません。プログラムが を読み取ろうとすると、エラーが発生しますm2.cells[0][0]

cells and dataデストラクタで削除しないとこのエラーは発生しません。

セルとデータを私のやり方で宣言します。これは、後でIntervall = Matrix[i][j]. また、算術演算子をオーバーロードして、 と書けるようにしたいと考えていますMatrix m3 = m2*m1。実際、私はすでにそれを行いました。それが最初にエラーが発生した場所です。

さて、最後に私の質問: デストラクタで割り当てられたメモリを解放しながら、メモリエラーを引き起こさない IntervallRMatrix を返す関数を実装するにはどうすればよいですか?

4

2 に答える 2

2

最善の解決策は、手動のメモリ管理を避けることです。適切なコンテナー (例: std::vector) またはスマート ポインターを使用します。

手動で管理する必要がある場合は、必ず3 つのルールに従ってください。

于 2013-01-31T15:50:06.397 に答える
0

ここでの問題は、clone メソッドが、スタック上に作成して初期化したばかりの結果オブジェクトのコピーを返すことです。コピー コンストラクターを実装していないため (確認できることから)、既定のコンストラクターがコンパイラによって提供されます。このデフォルトの実装は、基本的にメンバー変数をあるインスタンスから別のインスタンスにコピーします (この場合、セルとデータへのポインター)。コンテンツはまったく複製されません。クローン関数のスコープから出ると、結果オブジェクトは (プリデストラクター コードとして) 削除され、セルとデータ ポインターがまだ空きメモリを指している結果のコピーになります。これにより、未定義の動作が発生します (「クラッシュする」と読まれることがよくあります)。

Oli Charlesworth が答えたように、3 つのルールに従います。

于 2013-01-31T15:59:37.990 に答える