0

動的マトリックスを作成する必要があるすべての人がいます。これが私が持っているコンストラクターとデストラクタです。

Board::Board() {
    a_l=0;
    a_c=0;
    a_mp=NULL;
}
Board::Board(const Board&t) {
    a_l=t.a_l;
    a_c=t.a_c;
    a_mp=t.a_mp;
    Memory();
    copy(t);
}
Board::Board(int nl, int nc) {
    a_l=nl;
    a_c=nc;
    Memory();
}
Board::~Board() {
    freeMemory();
}

// PRIVATE METHODS

void Board::copy(const Board &t) {
    int a_l, a_c;
    int ** a_mp;
    a_l=t.a_l;
    a_c=t.a_c;
    for(int i=a_l;i<a_c;i++) {
        for(int j=a_c;j<a_l;j++) {
            a_mp[i][j]=t.a_mp[i][j];
        }
    }
}
void Board::freeMemory() {
    for(int i=0;i<a_l-1;i++) {
        delete [] a_mp[i];
    }
    delete [] a_mp;
}
void Board::Memory() {
    char ** a_mp;
    a_mp = new char*[a_l];
    for(int i =0;i<a_l; i++) {
        a_mp[i]=new char[a_c];
        for(int j=0;j<a_c;j++)
            a_mp[i][j]='-';
    }
}

Board はクラス、a_l と a_c は行列の行と列の数です。私のメインでは、Board 変数を宣言してから、次のようにします。

board=Board(5,5);

コンパイルされますが、表示したいときは、たとえば次のようになります。

cout << board.Cols() << endl;

これは方法です:

int Board::Cols() const {
    return (a_c);
}

0が表示されます。まるで、私が言ったパラメータでボードを作成しなかったかのようです。また、これを行うとプログラムがクラッシュするboard=Board(5,5);ため、デバッガーを使用すると、削除の次の行で停止すると表示されます。

board=Board(5,5);

なぜクラッシュするのか、宣言したボード変数の値が保持されないのかわかりません! 誰でも理由を知っていますか?

EDIT:rMemory =メモリ、それはプログラムからではなく、ここからのタイプでした

4

4 に答える 4

1

for(int i=0;i<a_l-1;i++)inはtofreeMemoryから実行されます。これは < である最後の i です。割り当てループ実行はであり、したがって からまで実行されるため、1 行が欠落しています。もう 1 行を割り当てます。i=0i=35-1for(int i =0;i<a_l; i++)i=0i=4

もう 1 つは、copy() は何をするのかということです。t.a_l と t.a_c の値を一時変数にコピーします。一時変数は、コピーが終了すると削除され、未割り当てのメモリ (一時的な **a_mp) に値を割り当てます。この関数内の宣言と割り当てを削除し、a_mp データ コピーのみを残します。

void Board::copy(Board const &t) {
    for(int i=a_l;i<a_c;i++) {
        for(int j=a_c;j<a_l;j++) {
            a_mp[i][j]=t.a_mp[i][j];
        }
    }
}

私がしたこと:

  • の a_mp の宣言を削除しますMemory()
  • 代入演算子を追加 -> 3 つのルールとは?
  • freeMemory() 関数で NULL ポインターをチェックする

次のようになります。

class Board
{
public:
  int a_l, a_c;
  char ** a_mp;

  Board() : a_l(0), a_c(0), a_mp(NULL) 
  {
  }
  Board(const Board&t) : a_l(t.a_l), a_c(t.a_c), a_mp(NULL) 
  {
    Memory();
    copy(t);
  }
  Board(int nl, int nc) : a_l(nl), a_c(nc), a_mp(NULL) 
  {
    Memory();
  }

  Board& operator= (Board const &t)
  {
    freeMemory();
    a_l = t.a_l;
    a_c = t.a_c;
    Memory();
    copy(t);
    return *this;
  }

  Board::~Board() 
  {
    freeMemory();
  }

  // PRIVATE METHODS

  void copy(const Board &t) 
  {
    for(int i=a_l;i<a_c;i++) 
    {
      for(int j=a_c;j<a_l;j++) 
      {
        a_mp[i][j]=t.a_mp[i][j];
      }
    }
  }
  void freeMemory() 
  {
    if (a_mp == NULL)
    {
      for(int i=0;i<a_l;i++) 
      {
        delete [] a_mp[i];
      }
      delete [] a_mp;
    }
  }
  void Memory() {
    a_mp = new char*[a_l];
    for(int i =0;i<a_l; i++) 
    {
      a_mp[i]=new char[a_c];
      for(int j=0;j<a_c;j++) a_mp[i][j] = '-';
    }
  }

  int Cols() const 
  {
    return (a_c);
  }

};

動作します。

Board testboard;
testboard = Board(5,5);
cout << "Cols are: " << testboard.Cols() << endl;

印刷物: "Cols are: 5".

于 2013-04-18T14:01:50.920 に答える
1
void Board::Memory() {
    char ** a_mp;
    a_mp = new char*[a_l];
    for(int i =0;i<a_l; i++) {
        a_mp[i]=new char[a_c];
        for(int j=0;j<a_c;j++)
            a_mp[i][j]='-';
    }
}

a_mp というスタック上のローカル変数を宣言しています。このポインタは、ヒープ上に割り当てられたすべてのメモリを指します。次に、Memory() への呼び出しの最後に範囲外になります。これで、割り当てたばかりのメモリにアクセスする方法がなくなりました。これは悲しいです。a_mp はメンバー変数である必要があります。これにより、メモリが終了した後もデータへの参照が保持されます。そして、デストラクタが解放するメモリを認識できるようにします。

つまり、次の行を削除します。char ** a_mp;

于 2013-04-18T14:02:29.133 に答える