2013-01-20 20 views
1

我已經爲三維數組創建了下一個類。聲明一個變量,例如動態三維數組的聲明和賦值

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

這是一個簡單的錯字。我要指出的線,我會讓你發現它不見了錯誤:

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

也就是說,除了缺少的賦值操作符,這使得n = Grid3d(2,2,2);原構造的對象被釋放,因而您正在使用NULL指針在operator()中訪問G[i][j][k]

+0

*完全*值得燃燒一個我的我的最終每日3票。 did * not * see that coming = P – WhozCraig