2013-03-13 3 views
-1

내 클래스의 동적 배열에 대해 복사 생성자 및 연산자 = 연산자를 구현하는 데 도움이 필요합니다. 필자는이 시점 여기클래스 내부의 동적 배열에 대한 생성자 및 연산자 복사

에서 벡터를 사용할 수 없습니다 MYE 코드는 다음과 같습니다 클래스 :

class Matrix{ 
    private: 
     int rows; 
     int columns; 
     double* matrix; 
    public: 
     Matrix(); 
     explicit Matrix(int N); 
     Matrix(int M, int N); 
     void setValue(int M, int N, double value); 
     double getValue(int M, int N); 
     bool isValid() const; 
     int getRows(); 
     int getColumns(); 
     ~Matrix(); 
     friend ostream& operator<<(ostream &out, Matrix&matrix1);  
}; 

그리고 내 코드 :이 작품 같은

Matrix::Matrix(){ 
    matrix = NULL; 
} 

Matrix::Matrix(int N){ 
    matrix = new double[N * N]; 
    rows = N; 
    columns = N; 

    for(int i = 0; i < N; i++){ 
     for(int j = 0; j < N; j++){ 
      if(i==j) 
       matrix[i * N + j] = 1; 
      else 
       matrix[i * N + j] = 0; 
     } 
    } 
} 

Matrix::Matrix(int M, int N){ 
    matrix = new double[M * N]; 
    rows = M; 
    columns = N; 

    for(int i = 0; i < M; i++){ 
     for(int j = 0; j < N; j++) 
      matrix[i * N + j] = 0; 
    } 
} 

Matrix::~Matrix(){ 
    delete [] matrix; 
} 

void Matrix::setValue(int M, int N, double value){ 
    matrix[M * columns + N] = value; 
} 

double Matrix::getValue(int M, int N){ 
    return matrix[M * columns + N]; 
} 

bool Matrix::isValid() const{ 
    if(matrix==NULL) 
     return false; 
    else 
     return true; 
} 

int Matrix::getRows(){ 
    return rows; 
} 

int Matrix::getColumns(){ 
    return columns; 
} 

ostream& operator<<(ostream &out, Matrix&matrix1){ 
    if(matrix1.isValid()) 
     for(int i = 0; i < matrix1.getRows(); i++){ 
      for(int j = 0; j < matrix1.getColumns(); j++) 
       out << matrix1.getValue(i,j) << "\t"; 
      out << endl; 
     } 
    else 
     out << "Matrisen er ikke gyldig."; //the matrix is not valid 
    return out; 
} 

겠습니까 뭔가?

Matrix &operator=(const Matrix &m) {*(this->matrix) = *(m.matrix);} 
Matrix(const Matrix &rhs) : matrix(0) { 
     this->matrix = new double(); 
     *(this->matrix) = *(rhs.matrix); 
    } 

또한 + = 및 + 연산자에 과부하가 발생합니다. 이 작품 같은

const Matrix operator+=(Matrix matrix1, Matrix matrix2){ 
     if(!matrix1.isValid() || !matrix2.isValid()){ 
      cout << "En av matrisene er ugyldig"; //one of the matrices are invalid 
      return Matrix::Matrix(); //returning a NULL matrix 
     } 
     else{ 
      if(matrix1.getColumns()==matrix2.getColumns() && matrix1.getRows()==matrix2.getRows()){ 
       Matrix temp(matrix1.getRows(), matrix1.getColumns()); 
       for(int i = 0; i < matrix1.getRows(); i++){ 
        for(int j = 0; j < matrix1.getColumns(); j++) 
         temp.setValue(i,j,(matrix1.getValue(i,j) + matrix2.getValue(i,j))); 
       } 
       return temp; 
      } 
      else{ 
       cout << "Matrisene har ikke samme dimensjon"; //the matrices does not have the same dimensions 
       return Matrix::Matrix(); 
      } 
     } 
    } 
    const Matrix operator+(Matrix matrix1, Matrix matrix2){ 
     return matrix1 += matrix2; 
    } 

겠습니까 뭔가 :이 등을 구현하기 위해 노력했습니다 ? 연산자를 클래스의 일부로, 클래스의 친구로 또는 클래스 외부로 오버로드하는 것이 좋습니다.

도움이 필요합니다.

+0

를 ++ 우리는 일반적으로 표준 라이브러리를 사용하십시오 : std :: vector, std :: map 등등. 그것은 훨씬 더 redable하고 덜 오류가 발생하기 쉽습니다. –

+0

나는 '* (this-> matrix) = * (m.matrix);'라는 문장을 기대한다. 작동하지 않으면 명시 적으로 메모리를 할당하고 memcpy 등을 사용하여 새 메모리를 할당해야합니다. –

+0

"using namespace std;"줄을 포함 시켰습니다. 또한 원래 파일의 코드 시작 부분에 "#include "이 있지만 게시 할 때 복사하지 않았습니다. 그것이 당신이 의미하는 바라면. – Ole1991

답변

1

왜 다른 질문을 삭제 했습니까? 그냥 오류가 있었으면 좋겠다. (끝 부분의 EDIT를 참조하십시오)

예, 코드 및 디자인에 많은 문제가 있습니다.

귀하의 매트릭스 더 복사 생성자가없는 (또는 이동)이 아니라 "="너무 :

그냥 당신에게 아이디어를 제공합니다. 그들은 :

Matrix(const Matrix &m); 

그리고 (이동 생성자) :이 특수 기능을 정의하지 않으면

Matrix(Matrix &&m); 

그리고

Matrix& operator=(const Matrix &m); 
Matrix& operator=(Matrix &&m); 

이 컴파일러는 당신을 위해 그것을 정의합니다. 그러나 그들은 분명히 작동 할 것입니다. 프로그램이 컴파일되지만 잘못 작동합니다 (얕은 복사와 깊은 복사 문제이 전달되거나 참조 번호으로 전달됨). 생성자에서 new을 사용하여 matrix 개인 배열을 빌드합니다. 그리고 소멸자가 너 delete[]matrix. Matrix을 값으로 전달할 때마다 Matrix 멤버의 값을 복사하여 컴파일러 생성 된 복사본 생성자를 사용하여 복사 한 다음 배열의 값이 아닌 포인터 matrix의 값을 복사합니다. 전화가 끝나면이 로컬 복사본이 삭제되고 원본 매트릭스가 삭제됩니다 !! 이것은 많은 문제 중 하나 일뿐입니다. 앉을 충분한, 쓰레기를 더 읽고 나중에 다시 시도하십시오. A "간단한"수정은 어쩌면 이제 컴파일러 생성 기능이 더 많이 작동합니다

std::vector<double> matrix; 

에 의해

double *matrix; 

을 대체한다.

예, []Matrix과 함께 사용하려면이 값을 정의해야합니다. +=은 이진 연산자이며 하나의 매개 변수를 사용합니다 (왼쪽은 항상 this이며 호출하는 개체에 대한 포인터 임). 여기에 2 개의 인수가있는 +()을 무료로 원하거나 +() 구성원을 하나만 갖고 싶습니다. 희망이 도움이됩니다. 다시 물어보십시오.

편집 : operator=으로 작동합니까?

Matrix &operator=(const Matrix &m) {*matrix = *(m.matrix);} 

아니요. 첫 번째 이중 만 복사합니다. Entery 배열에 대한 루프가 필요하며 각 요소를 복사하십시오. 그리고 먼저 행렬의 크기가 호환되는지 확인해야합니다. (사용하는 경우 vectormatrix=m.matrix가 작동합니다.) 이다, 당신은 원래 값을 걱정하지 않을 때

Matrix::Matrix( Matrix &&m): rows (m.rows), 
            columns (m.columns), 
            matrix (m.matrix) 
{ 
    m.matrix=nullptr; 
    m.rows= m.columns=0; 
} 

이 움직임은 극적으로 매트릭스 대처의 효율성을 향상시킬 수

Matrix::Matrix(const Matrix &m): rows (m.rows), 
            columns (m.columns), 
            matrix (new double[rows* columns]) 
{ 
    for(int i = 0; i < rows; i++) 
     for(int j = 0; j < columns; j++) 
      matrix[i * columns + j] = m.matrix[i * columns + j]; 

} 

그리고 이동 : 당신의 복사 생성자에 대한 수정이 될 수있다 예를 들어 시간적 대상이있는 경우. 이 경우 각 배열 요소를 반복하여 복사 할 필요가 없습니다. 전체 배열을 간단히 훔칠 수 있습니다. 그것에 대한 좋은 점은 대부분의 상황에서 컴파일러가 올바른 변종 (복사 또는 이동)을 "자동"선택한다는 것입니다.

+0

예, 죄송합니다. 답장을 보내 주셔서 감사합니다. Im은 당신이 제안하는 것처럼이 시점에서 벡터를 사용하는 것을 허용하지 않았지만, ill는 operator =에 대한 루프를 만듭니다. 감사! – Ole1991

+0

Ive는 귀하와 Kristian의 솔루션을 복사 생성자와 연산자 =에 구현했지만 이동 생성자는 무엇을합니까? 필요합니까? – Ole1991

+0

@ Ole1991 이동에 대한 마지막 편집을보십시오. – qPCR4vir

1
Matrix &operator=(const Matrix &m) {*(this->matrix) = *(m.matrix);} 

이렇게하면 lhs '행렬의 첫 번째 요소가 rhs 행렬의 첫 번째 요소와 동일하게 할당됩니다. 게다가 두 행렬 모두 같은 수의 행과 열로 초기화해야합니다. memcpy 또는 루프를 사용하여 모든 요소를 ​​지정할 수 있습니다.

Matrix(const Matrix &rhs) : matrix(0) { 
    this->matrix = new double(); 
    *(this->matrix) = *(rhs.matrix); 
} 

(다른 매트릭스는 1x1 매트릭스가 아닌 경우) 당신이 새롭게 구축되는 인스턴스의 매트릭스 구성원에 대한 충분한 메모리를 할당하지 않기 때문에이 실패합니다. 행렬은 행 주요 순서로 저장되어 있다고 가정하면, 그것은 다음과 같아야합니다

Matrix(const Matrix &rhs) : matrix(0), rows(rhs.rows), columns(rhs.columns) { 
    this->matrix = new double[rows * columns]; 
    for (size_t r = 0; r < rows; r++) { 
     for (size_t c = 0; c < columsn; c++) { 
      this->matrix[r * columns + c] = rhs.matrix[r * columns + c]; 
     } 
    } 
} 

편집 : 그냥 확인하고, 여기에 내가 할당 연산자 할 것입니다 방법은 다음과 같습니다 C에서

Matrix &operator=(const Matrix &m) { 
    if (rows * columns != m.rows * m.columns) { 
     delete [] this->matrix; 
     this->matrix = new double[m.rows * m.columns]; 
    } 
    rows = m.rows; 
    columns = m.columns; 
    for (size_t r = 0; r < rows; r++) { 
     for (size_t c = 0; c < columsn; c++) { 
      this->matrix[r * columns + c] = m.matrix[r * columns + c]; 
     } 
    } 
    return *this; 
} 
+0

고마워요! 일리노이가 =에 대한 루프를 만듭니다. – Ole1991

+0

모든 것이 완벽하게 작동합니다. + = 연산자와 + 연산자의 오버로드도 마찬가지입니다. 고맙습니다:) – Ole1991