1

ポインターの 2D 配列の問題に直面しています。エラーなしでコンパイルされますが、ファイルを実行しようとすると、セグメンテーション違反があることを示す 1 行しか表示されません。

私のヘッダーファイル:

#ifndef __TWODARRAY_H__
#define __TWODARRAY_H__

template <typename T>
class TwoDArray {
  private:
    T** theArray;
    int numRows;
    int numCols;
    T defSpace;

  public:
    TwoDArray<T> (int r, int c, T def);
    ~TwoDArray<T>();
    void insert(int r, int c, T value);
    T access(int r, int c);
    void remove(int r, int c);
    void print();
    int getNumRows();
    int getNumCols();
};
#endif

私の方法:

#include "TwoDArray.h"
#include <iostream>
#include <assert.h>
#include <string>

//initializes the 2D Array
template <typename T>
TwoDArray<T>::TwoDArray(int r, int c, T def) {
  assert(r > 0 && c > 0);
  numRows = r;
  numCols = c;
  defSpace = def;
  theArray = new T*[r];
  for(int i=0; i<r; i++) {
    theArray[i] = new T[c];
  }
  //sets all values to the default
  for(int i=0; i<r; i++) {
    for(int j=0; j<c; j++) {
    theArray[i][j] = defSpace;
    }
  }
}

//deletes the 2D Array
template<typename T>
TwoDArray<T>::~TwoDArray() {
  for(int i=0; i<numRows; i++) {
    delete[] theArray[i];
  }
  delete[] theArray;
}

//inserts value v at row r and column c
template<typename T>
void TwoDArray<T>::insert(int r, int c, T value) {
  assert(r < numRows && c < numCols);
  assert(value != defSpace);
  theArray[r][c] = value;
}

//get value at row r, column c
template<typename T>
T TwoDArray<T>::access(int r, int c) {
  assert(r < numRows && c < numCols);
  T result = theArray[r][c];
  return result;
}

//set value at row r and column c back to default
template<typename T>
void TwoDArray<T>::remove(int r, int c) {
  assert(r < numRows && c < numCols);
  assert(theArray[r][c] != defSpace);
  theArray[r][c] = defSpace;
}

//print the 2D Array
template<typename T>
void TwoDArray<T>::print() {
  for(int i=0; i<numRows; i++) {
    for(int j=0;j<numCols; i++) {
      std::cout << theArray[i][j];
      std::cout << " ";
    }
    std::cout << std::endl;
  }
}

//gets number of rows for test
template<typename T>
int TwoDArray<T>::getNumRows() {
  return numRows;
}

//gets number of columns for test
template<typename T>
int TwoDArray<T>::getNumCols() {
  return numCols;
}

template class TwoDArray<int>;
template class TwoDArray<std::string>;

そして私のメイン:

#include <iostream>
#include <string>
#include "TwoDArray.h"

using std::cout;
using std::endl;

int main() {
  TwoDArray<int>* i = new TwoDArray<int>(5, 5, 0);

  TwoDArray<std::string>* s = new TwoDArray<std::string>(5, 5, "o");

  i->insert(1, 1, 1);
  i->insert(1, 3, 1);
  i->insert(3, 2, 8);
  i->insert(2, 0, 3);
  i->insert(2, 4, 3);
  i->insert(3, 2, 8);

  i->print();


  s->insert(0, 2, "North");
  s->insert(4, 2, "South");
  s->insert(2, 4, "East");
  s->insert(2, 0, "West");

  s->print();

  return 0;
}

セグメンテーション違反が発生する理由はありますか?

4

1 に答える 1

5

これは間違いです:

template<typename T>
void TwoDArray<T>::print() {
  for(int i=0; i<numRows; i++) {
    for(int j=0;j<numCols; i++) {   // should be j++, not i++
      std::cout << theArray[i][j];
      std::cout << " ";
    }
    std::cout << std::endl;
  }
}

asiは外側と内側の両方でインクリメントされ、for最終的にi等しくnumRowsなり、配列の末尾を 1 つ過ぎます。これは未定義の動作であり、セグメンテーション違反の原因となる可能性があります。

動的に割り当てられたメンバーがTwoDArrayあるため、インスタンスのコピーを防止するTwoDArrayか、代入演算子とコピー コンストラクターを実装する必要があります ( What is The Rule of Three? を参照)。

これが学習演習でない場合は、vector<vector<T>>代わりに a を使用できます。

また、配列の次元はコンパイル時の定数であるため、それらをテンプレート パラメーターにして、動的メモリを完全に回避することもできます。

template <typename TType, int TRows, int TCols>
class TwoDArray {
  private:
    TType theArray[TRows][TCols];
    TType defSpace;
    ....

TwoDArray<int, 5, 5> i(0);

完全なデモについては、 http://ideone.com/dEfZn5を参照してください。

于 2012-10-25T19:13:52.367 に答える