2013-01-20 2 views
1

3D 배열에 대해 다음 클래스를 만들었습니다.동적 3D 배열 선언 및 지정

Grid3d n = Grid3d(2,2,2); 
n(0,0,0) = 1; 

잘 작동 예를 들어, 같은 변수를 선언하지만,

Grid3d n; 
n = Grid3d(2,2,2); 
n(0,0,0) = 1; 

로 선언하는 것은 나에게 세그먼트 오류를 ​​제공, 문제는 기본 생성자 것 같다,하지만 난 방법을 모른다 그것을 해결하기 위해, 어떤 단서?

#ifndef _GRID3D_ 
#define _GRID3D_ 

#include <iostream> 
#include <cmath> 
#include <cassert> // assert() 

using namespace std; 

class Grid3d 
{ 
private: 
    int L; 
    int M; 
    int N; 
    double *** G; 

public: 
    Grid3d(int,int,int); 
    Grid3d(); 
    Grid3d(const Grid3d &); 
    ~Grid3d(); 

    double & operator()(int,int,int); 
}; 
#endif 

//Constructor 
Grid3d::Grid3d(int L,int M,int N) 
    :L(L), M(M), N(N) 
{ 
    int i,j,k; 
    G = new double ** [L]; 
    for (i=0;i<L;i++){ 
     G[i] = new double * [M]; 
     for (j=0;j<M;j++){ 
      G[i][j] = new double [N]; 
      for (k=0;k<N;k++){ 
       G[i][j][k] = 0; 
      } 
     } 
    } 
} 

//Constructor vacío 
Grid3d::Grid3d() 
    :L(0), M(0), N(0) 
{ 
    G = NULL; 
} 

//Constructor copia 
Grid3d::Grid3d(const Grid3d &A) 
    :L(A.L), M(A.M), N(A.N) 
{ 
    G = new double ** [L]; 
    int i,j,k; 
    for (i=0;i<L;i++){ 
     G[i] = new double * [M]; 
     for (j=0;j<M;i++){ 
      G[i][j] = new double [N]; 
      for (k=0;k<N;k++){ 
       G[i][j][k] = A.G[i][j][k]; 
      } 
     } 
    } 
} 

//Destructor 
Grid3d::~Grid3d() 
{ 
    // Libera memoria 
    for (int i=0;i<L;i++){ 
     for (int j=0;j<M;j++){ 
      delete [] G[i][j]; 
      G[i][j] = NULL; 
     } 
     delete [] G[i]; 
     G[i] = NULL; 
    } 
    delete G; 
    G = NULL; 
} 

double& Grid3d::operator()(int i,int j,int k) 
{ 
    assert(i >= 0 && i < L); 
    assert(j >= 0 && j < M); 
    assert(k >= 0 && k < N); 
    return G[i][j][k]; 
} 

할당 연산자

Grid3d Grid3d::operator = (const Grid3d &A) 
{ 
    if (this == &A) {return *this;}; 
    if (G != NULL){ 
     // Libera memoria 
     for (int i=0;i<L;i++){ 
      for (int j=0;j<M;j++){ 
       delete [] G[i][j]; 
       G[i][j] = NULL; 
      } 
      delete [] G[i]; 
      G[i] = NULL; 
     } 
     delete G; 
     G = NULL; 
    } 

    L = A.L; 
    M = A.M; 
    N = A.N; 
    G = new double ** [L]; 
    int i,j,k; 
    for (i=0;i<L;i++){ 
     G[i] = new double * [M]; 
     for (j=0;j<M;i++){ 
      G[i][j] = new double [N]; 
      for (k=0;k<N;k++){ 
       G[i][j][k] = A.G[i][j][k]; 
      } 
     } 
    } 
    return *this; 
} 
+2

할당 연산자가 없습니다. – juanchopanza

+0

#endif 문이 클래스 정의의 중간에있는 이유는 무엇입니까? – ApproachingDarknessFish

+0

#endif는 2 파일에 클래스의 선언과 구현이 있기 때문에 존재합니다. – user1995432

답변

2

메모리를 동적으로 할당했지만 사용자가 rule of three을 따르지 않았습니다. 당신은 할당 연산자 누락, 그래서 당신이 할 때 :

Grid3d n; 
n = Grid3d(2,2,2); // both RHS temporary and n point to the same data. 
n(0,0,0) = 1;  // Accessing deleted memory: undefined behaviour. 

당신은 두 개의 동일한 메모리의 해제 할당을 시도해야합니다 당신은 임시 사용 된 것과 동일한 메모리에 n의 포인터를 가리키는을 가지고 있기 때문에 두 번째 줄에 할당하십시오. 임시가 죽으면 메모리를 할당 해제합니다. n이 죽으면 같은 메모리를 할당 해제하려고 시도합니다. 또한, 두 번째 줄 이후의 해당 메모리에 대한 액세스는 정의되지 않은 동작입니다.

+0

소멸자가 G의 내부 포인터를 NULL로 설정했기 때문에 사실 operator()의 액세스가 잘못되었습니다 - 실제로 컴파일하고 실행하여 확인했습니다. –

+0

@MatsPetersson 예, 코드 샘플에 주석을 추가했습니다. 그러나 액세스가 없더라도 결국에는 이중 삭제가 발생합니다. – juanchopanza

+0

완전히 동의하십시오. –

2

그것은 사소한 오타입니다. 나는 선을 지적거야, 내가 잘못 사라 졌어요 위치를 자리 드리겠습니다 : n = Grid3d(2,2,2);의 원래 구성 개체가 해제 될 수 있습니다 누락 대입 연산자, 제외입니다

for (j=0;j<M;i++) 

, 따라서 NULL 포인터가있는 G[i][j][k]operator()을 액세스하고 있습니다.

+0

* 완전히 가치가있는 하나의 내 my 이것에 대한 최종 3 일 투표. didn''t는 오는 것을 보았습니다 * P – WhozCraig